【问题标题】:Possible to force memory alignment on pointer param in C?可以在 C 中强制指针参数上的内存对齐吗?
【发布时间】:2017-01-27 15:51:22
【问题描述】:

我在 C 中有一个函数,它接受 uint8_t * 参数,它必须指向 32 位对齐的内存。是否可以在 C 或 C++ 或任何特定平台的宏中为参数添加一些修饰,以便编译器或链接器在构建时如果未按要求对齐会抛出错误?

这里的想法是我想保护该功能不被其他用户(或我在 6 个月内)不当使用。我知道如何对齐我想传递给它的东西。我想确保没有人可以将未对齐的东西传递给它。

基于this answer,我认为我的问题的答案是“否”,不可能在构建时强制执行,但它似乎是一个有用的功能,所以我想我会检查一下。我的解决方法是将assert((((size_t)ptr) % 4) == 0);放在函数中,这样至少我可以在调试时在运行时捕获它。

根据我的经验,如果您在许多嵌入式平台上将未对齐的 uint8_t* 转换为 uint32_t*,结果是不确定的,因此我不想指望最终会出现“正确”的结果。另外,这是在实时系统上使用的,因此速度变慢可能是不可接受的。

欢迎引用,如果有的话。

【问题讨论】:

  • 确定不是XY问题? Intel 上的未对齐访问几乎是无惩罚的,而在严格对齐架构上它无论如何都会导致 SIGBUS。
  • 您会如何期望在buld time 出现错误?这需要编译器做很多事情,如果我这样做uint8_t* sneaky = (uint8_t*) 1; alignmentRequiringFunction(sneaky); 会怎样?或者如果sneaky 的值来自fgets()?至少向调用者表明您期望的一种解决方法是将参数设为uint32_t *,因为这意味着需要自然对齐。
  • @cp.engr 在我看来,链接器(而不是编译器)可以假设我在运行时执行相同的对齐检查。 如何?指针值在链接时通常是未知的。
  • 由于平台显然非常具体,是否可以选择重新实现或包装 mallocfree 以仅使用对齐的内存?
  • 据我所知,在 C++ 中可以全局重载 newdelete 运算符。

标签: c++ c c-preprocessor memory-alignment


【解决方案1】:

不,我所知道的 C 或 C++ 标准中没有任何内容可以强制指针参数保持适当的值。

要获取内存,请使用posix_memalign

#include <stdlib.h>

int posix_memalign(void **memptr, size_t alignment, size_t size);

描述

posix_memalign() 函数应分配 size 字节对齐在 由对齐指定的边界,并应返回指向 在 mempr 中分配的内存。对齐的值应为 sizeof(void *) 的两个倍数。

成功完成后,mempr 指向的值应为 对齐的倍数。

【讨论】:

  • 很高兴知道,但我在资源受限的嵌入式平台上,为实时系统开发裸机固件,所以我们静态声明所有内容。
  • @cp.engr 如果您将数据声明为uin32_t 而不是uint8_t事实上 unsigned char,我怀疑),您的平台是否强制执行 32-位对齐?
  • 是的,但我试图在传递参数之前抽象出转换的需要。 (确实,低级函数将uint8_t* 转换为uint32_t*。)我想我也不能吃蛋糕吗?
  • @cp.engr 为什么不将您的数据定义为uint32_t?我希望这会正确对齐。
  • 想想该功能的未来用户,而不仅仅是我现在。我知道如何对齐要传递给它的结构/数组。
【解决方案2】:

对于动态分配,请查看标准(自 C11 起)aligned_alloc

对于静态分配,我不知道标准方法,所以它取决于编译器。对于 gcc,例如,检查 aligned attribute

【讨论】:

  • aligned_alloc() 是 C++ 的一部分吗? This question and its answers 几个月大了。至于静态对齐,在我工作过的每个平台上,对于一个类型都有对齐要求,任何好的编译器都可以正确对齐这些类型,所以在这种情况下,我希望 static uint32_t data[...]; 可以在任何平台上自然对齐- 需要对齐。
  • @AndrewHenle:我的答案是针对 C 语言的。对于 C++,您还有其他选择,例如 alignasaligned_storage 或新位置。关于。自然对齐 - 这听起来很合理,但我不确定您是否可以依赖这种行为,因此查阅您的平台文档可能是个好主意。
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多