【问题标题】:Compiler Warning when using Pointers to Packed Structure Members使用指向压缩结构成员的指针时的编译器警告
【发布时间】:2015-05-05 17:12:36
【问题描述】:

许多 C/C++ 编译器(包括 gcc 和 clang)都有一个称为打包结构的功能。由于多种原因,它派上用场,但必须谨慎使用。一个潜在的陷阱是您使用指向结构成员的指针作为另一个函数的参数。现在该函数不知道未对齐的指针。让我用一些代码来说明我的意思:

#pragma pack(1)
typedef struct { int x; } uas;
#pragma pack()

void foo(int *f) {
  // some code using the value of *f
}
void bar(uas *b) {
  foo(&(b->x));
}

int 在 32 位机器上的对齐方式通常是 4。编译器现在可以为 foo() 生成代码,如果 f 不是 4 字节对齐的,则可能无法工作。旧 ARM 架构就是这种情况。

现在 struct uas 和其中的所有成员的对齐保证为 1。显然,将 b->x 的地址传递给 foo() 是个坏主意。

GCC 和 clang 有一个编译器警告 (-Wcast-align),例如,通过将 char* 转换为 int* 来触发该警告。即使两者都支持,使用指向压缩结构成员的指针似乎也不会触发此警告。我也试过-Wall-Wextra,但它们甚至不包括-Wcast-align

我的主要问题是 GCC、clang 或任何其他支持打包结构的编译器是否有一个由上面的特定示例触发的警告。看来,如果编译器支持打包结构,则这样的警告是强制性的。

【问题讨论】:

  • 这非常接近this question,尽管更具体。不过,该答案中提到的The GCC bug report 专门讨论了指针。
  • 好吧,如果你有这样一个打包的结构/类,你只传递目标中的起始地址和取消引用,这样可以避免传递未对齐变量的地址。如果开发者做了奇怪的事情,那么奇怪的事情就会发生。
  • 有些人会犯错误。其他人不知道并且基本上接受他们机器上的任何工作都是“正确的”。这就是为什么我们有程序给我们“提示”人类可能做过坏事的原因。对这种特殊情况有一个“提示”真的很有意义。
  • 您是否尝试在不允许非对齐访问整数的拱门上编译它?在 x86 上,现在不仅允许而且速度更慢(感谢缓存)。
  • 我尝试为 ARM 进行交叉编译。我什至用clang尝试了-Weverything。

标签: c++ c pointers struct memory-alignment


【解决方案1】:

clang 刚刚为此特定问题添加了新的 -Waddress-of-packed-member 警告。有关详细信息,请参阅 https://reviews.llvm.org/rL278483https://llvm.org/bugs/show_bug.cgi?id=22821。它应该出现在 clang 的 4.0 版本中。

【讨论】:

    【解决方案2】:

    gcc 刚刚在 gcc-9 中添加了相同的警告 (-Waddress-of-packed-member)。使用-Wall时默认开启

    【讨论】:

      【解决方案3】:

      考虑 typedef 结构定义的以下对齐方式:

      #pragma pack(1)
      typedef struct { int x; } uas __attribute__ ((aligned (sizeof(uint32_t))));
      #pragma pack()
      

      这将通知编译器确保结构的所有分配都是 4 字节对齐的。

      参考是here

      【讨论】:

      • 考虑在结构中使用char a; int x;。那么a 将位于4*k 形式的地址,x 将位于4*k+1 形式的地址,其中k 是一个整数。
      猜你喜欢
      • 2021-07-17
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多