【发布时间】:2016-01-23 19:21:08
【问题描述】:
我们运行的测试之一是使用-Wcast-align 进行编译。当浮点数、双精度数和整数之间发生错误转换时,它特别有用(有时会导致 SIGBUS,IIRC)。
我们的代码基本上执行以下操作。实际案例稍微多一些,但这是用法的精髓:
typedef uint64_t word64;
static const size_t SIZE = ...;
word64 buffer[SIZE] = ...;
还有:
DoSomethingWithBuffer(const byte* buff, size_t size)
{
word64* ptr = (word64*)buff;
...
}
缓冲区在 8 或 16 字节边界上对齐。我已经使用手动代码审查和运行时断言验证了对齐方式。
问题在于 GCC 和 Clang 都警告数据未对齐。它做了将近 2000 次,所以我可能会丢失真正的发现。例如:
warning: cast from 'const byte *' (aka 'const unsigned char *') to 'word64 *'
(aka 'unsigned long long *') increases required alignment from 1 to 8 [-Wcast-align]
word64 tmp = *(word64 *)inBlock ^ roundKeys[0];
^~~~~~~~~~~~~~~~~
使用 Clang,我可以使用 assert 进行检测,编译器有时会将其作为诊断提示。但它似乎不适用于这种情况。也就是说,Clang 没有建立 assert(inBlock % 8 == 0); 表示其对齐的连接。
如何在不抑制警告的情况下向编译器传达缓冲区已对齐?
【问题讨论】:
-
1) 使用
stdint.h固定宽度类型。 2) C 标准中的alignas有什么问题? 3) 您的代码可能会调用未定义的行为。 -
@Olaf - 谢谢。我们的测试计划相当全面。我们要求代码通过 Clang 和 GCC Undefined Behavior Sanitizer 的安全门,它们明确测试未对齐的访问。我们还要求它通过 Valgrind、Coverity 和 Microsoft Enterprise Analysis。此外,断言显式检查条件并且不会触发。所以我不相信它在这个特定领域会遭受 UB(我希望不会在任何领域)。
-
您可以尝试将其与编译器对齐的另一种类型合并,例如
double. -
你甚至没有检查我假设的
alignas(resp._Alignas) 说明符是什么。 -
@jww:它也是 C11 以来的 C 标准特性。请记住,只有一个 C 标准。仅供参考,该功能是有意添加到两种语言中的(类似于原子,顺便说一句。)
标签: c gcc casting clang compiler-warnings