gpt4 book ai didi

c - 加载未对齐的地址和 UBsan 发现

转载 作者:太空狗 更新时间:2023-10-29 14:53:50 24 4
gpt4 key购买 nike

这个问题不是关于未对齐数据访问的定义,而是为什么 memcpy 沉默了 UBsan 的发现,而类型转换却没有,尽管生成了相同的汇编代码。

我有一些示例代码来解析发送字节数组的协议(protocol),该字节数组被分成六个字节的组。

void f(u8 *ba) {
// I know this array's length is a multiple of 6
u8 *p = ba;
u32 a = *(u32 *)p;
printf("a = %d\n", a);
p += 4;
u16 b = *(u16 *)p;
printf("b = %d\n", b);

p += 2;
a = *(u32 *)p;
printf("a = %d\n", a);
p += 4;
b = *(u16 *)p;
printf("b = %d\n", b);
}

在将我的指针递增 6 并执行另一个 32 位读取后,UBSan 报告有关加载未对齐的错误。我使用 memcpy 而不是类型双关来抑制此错误,但我不太了解原因。需要明确的是,这是没有 UBSan 错误的相同例程,

void f(u8 *ba) {
// I know this array's length is a multiple of 6 (
u8 *p = ba;
u32 a;
memcpy(&a, p, 4);
printf("a = %d\n", a);
p += 4;
memcpy(&b, p, 2);
printf("b = %d\n", b);

p += 2;
memcpy(&a, p, 4);
printf("a = %d\n", a);
p += 4;
memcpy(&b, p, 2);
printf("b = %d\n", b);
}

两个例程都编译为相同的汇编代码(使用 movl 进行 32 位读取,使用 movzwl 进行 16 位读取),那么为什么一个未定义的行为是另一个不是? memcpy 是否有一些特殊的属性可以保证某些东西?

我不想在这里使用 memcpy,因为我不能依赖编译器对其进行足够好的优化。

最佳答案

UB sanitizer 用于检测代码不严格符合,实际上取决于无法保证的未定义行为。

实际上,C 标准指出,只要您将指针指向地址未适当对齐的类型,行为就是未定义的。 C11 (draft, n1570) 6.3.2.3p7 :

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned 68) for the referenced type, the behavior is undefined.

u8 *p = ba;
u32 *a = (u32 *)p; // undefined behaviour if misaligned. No dereference required

this 转换的存在允许编译器假定 ba 对齐到 4 字节边界(在 u32 是需要因此对齐,许多编译器将在 x86 上执行此操作),之后它可以生成假定对齐的代码。

即使在 x86 平台上,也有一些指令会失败: innocent-looking code可以编译成机器代码,在运行时导致中止。 UBSan 应该在代码中捕获这个代码,否则在您运行它时看起来很正常并且表现“如预期”,但如果使用另一组选项或不同的选项编译则会失败优化级别。

编译器可以为 memcpy 生成正确的代码 - 而且经常会,但这只是因为编译器会知道未对齐的访问将在目标平台上运行并表现良好。

最后:

I don't want to use memcpy here because I can't rely on compilers doing a good enough job optimising it.

你在这里说的是:“我希望我的代码在被垃圾编译器或产生缓慢代码的二十年前的编译器编译时可靠地工作。绝对不是在编译时与可以优化它以快速运行的那些。”

关于c - 加载未对齐的地址和 UBsan 发现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47619944/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com