gpt4 book ai didi

c++ - 使用 clang sanitizer 在指针数组中转换和写入报告未对齐的地址

转载 作者:行者123 更新时间:2023-11-30 01:34:27 27 4
gpt4 key购买 nike

我正在使用 char* 数组来存储不同的数据类型,如下例所示:

int main()
{
char* arr = new char[8];
*reinterpret_cast<uint32_t*>(&arr[1]) = 1u;
return 0;
}

用clang UndefinedBehaviorSanitizer编译运行会报如下错误:

runtime error: store to misaligned address 0x602000000011 for type 'uint32_t' (aka 'unsigned int'), which requires 4 byte alignment

我想我可以用另一种方式来做,但为什么会出现这种未定义的行为?这里涉及到哪些概念?

最佳答案

您不能将任意 char* 转换为 uint32_t*,即使它指向一个大到足以容纳 uint32_t 的数组>

有几个原因。

实际答案:

uint32_t 通常喜欢 4 字节对齐:它的地址应该是 4 的倍数。

char 没有这样的限制。它可以存在于任何地址。

这意味着对于 uint32_t,任意 char* 不太可能正确对齐。

语言律师回答:

除了对齐问题之外,您的代码还表现出未定义的行为,因为您违反了严格的别名规则。您正在写入的地址不存在 uint32_t 对象,但您将其视为存在一个对象。

一般来说,虽然 char* 可用于指向任何对象并读取其字节表示,但 T* 用于任何给定类型 T不能用于指向字节数组并将对象的字节表示写入其中。


无论错误的原因是什么,修复方法都是一样的:

如果您不关心将字节视为 uint32_t 而只是将它们序列化(例如通过网络发送或写入磁盘),那么您可以 std::copy 字节到缓冲区:

char buffer[BUFFER_SIZE] = {};
char* buffer_pointer = buffer;
uint32_t foo = 123;
char* pfoo = reinterpret_cast<char*>(&foo);
std::copy(pfoo, pfoo + sizeof(foo), buffer_pointer);
buffer_pointer += sizeof(foo);
uint32_t bar = 234;
char* pbar = reinterpret_cast<char*>(&bar);
std::copy(pbar, pbar + sizeof(bar), buffer_pointer);
buffer_pointer += sizeof(bar);
// repeat as needed

如果您确实想将这些字节视为uint32_t(如果您正在实现类似std::vector的数据结构,例如)那么您将需要确保缓冲区正确对齐,并使用 placement-new:

std::aligned_storage_t<sizeof(uint32_t), alignof(uint32_t)> buffer[BUFFER_SIZE];
uint32_t foo = 123;
uint32_t* new_uint = new (&buffer[0]) uint32_t(foo);
uint32_t bar = 234;
uint32_t* another_new_uint = new (&buffer[1]) uint32_t(foo);
// repeat as needed

关于c++ - 使用 clang sanitizer 在指针数组中转换和写入报告未对齐的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56386527/

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