C语言 由于malloc的结果似乎不能保证与任何东西对齐,它甚至可用吗?



我最近了解到,对某个对象(uint32_t* foo = (uint32_t*)7; *foo = 5;)未对齐的指针解引用实际上是未定义的行为:

C11第6.2.8节:对象对齐:

完整的对象类型有对齐要求对该类型对象可能所在地址的限制分配。对齐是实现定义的整数值表示连续地址之间的字节数可以分配给定的对象。对象类型强制对齐对该类型的每个对象的要求:可以进行更严格的对齐请求使用_Alignas关键字。

好的,很有趣。但malloc似乎并不关心对齐:

7.22.3.4malloc

函数简介

#include <stdlib.h>
void *malloc(size_t size);

描述

malloc函数为大小为的对象分配空间

返回

malloc函数返回空指针或指向已分配空间的指针。

因此:是否有一个非常真实的机会,做下面的事情调用未定义的行为?

uint32_t* a = malloc(10*sizeof(uint32_t));
*a = 7;

毕竟,我们不能保证malloc的返回值与任何值对齐。

您似乎跳过了标准的一段,而不是您引用的关于malloc函数的部分。从这个C17标准草案中——在C11和其他标准的后续版本中也是一样的(我粗体强调):

7.22.3内存管理函数

1连续调用aligned_alloc,callocmallocreallocfunctions未指定。指针返回如果分配成功被适当地对齐,以便可以分配指向具有基本对齐的任何类型对象的指针要求,然后用于访问这样的对象或这样的数组对象在已分配的空间中(直到显式地收回)。已分配对象的生存期从分配直到重新分配。每次这样的分配应产生一个指向与任何其他对象不相交的对象的指针。的指针返回的对象指向分配的对象的起始地址(最低字节地址)空间。如果不能分配空间,则返回空指针。如果请求的空间大小为零,则行为为实现定义的:返回空指针来指示错误,或者行为就好像大小是非零值,返回的指针不能用于访问对象对象。

所以,你的问题的基本前提是错误的,(成功)调用malloc返回的指针将可用于几乎任何类型的对象,就其对齐要求而言。对于具有扩展对齐要求的对象,的情况可能会不同,在这种情况下,应该使用更具体的分配技术。

相关内容

最新更新