首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用clang消毒器在指针数组中进行强制转换和写入报告未对齐的地址

使用clang消毒器在指针数组中进行强制转换和写入报告未对齐的地址
EN

Stack Overflow用户
提问于 2019-05-31 06:42:03
回答 1查看 320关注 0票数 1

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

代码语言:javascript
复制
int main()
{
    char* arr = new char[8];
    *reinterpret_cast<uint32_t*>(&arr[1]) = 1u;
    return 0;
}

使用clang UndefinedBehaviorSanitizer编译和运行时将报告以下错误:

代码语言:javascript
复制
runtime error: store to misaligned address 0x602000000011 for type 'uint32_t' (aka 'unsigned int'), which requires 4 byte alignment

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-31 07:41:15

即使指向足以容纳** char*的数组,也不能将任意的 uint32_t 强制转换为 uint32_t***

有几个原因。

实用的答案是:

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

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

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

律师回答的语言是:

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

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

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

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

代码语言:javascript
复制
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

如果您确实希望将这些字节视为新的放置(例如,如果您正在实现std::vector新数据结构),那么您将需要确保缓冲区正确对齐,并使用uint32_t --like:

代码语言:javascript
复制
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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56386527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档