我最近了解到,对某个对象(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
函数为大小由size指定且值不确定的对象分配空间。
退货
malloc
函数返回一个空指针或一个指向已分配空间的指针。
因此:像下面这样的行为调用未定义行为的可能性不是很真实的吗?
uint32_t* a = malloc(10*sizeof(uint32_t));
*a = 7;
毕竟,我们不能保证malloc
的返回值与任何值对齐。
1条答案
按热度按时间fwzugrvs1#
在引用
malloc
函数的部分之前,你似乎跳过了标准中的一个段落,从this C17 Draft Standard开始--在C11和其他更高版本的标准中也是如此(粗体强调是我的):7.22.3内存管理功能
1 由对
aligned_alloc
、calloc
、malloc
、未指定和realloc
函数。分配成功时返回的指针***已适当对齐,以便可以将其分配给指向具有基本对齐要求的任何类型对象的指针***然后用于访问所分配的空间中的这样的对象或这样的对象的阵列(直到空间被显式释放)。已分配对象的生存期从分配到释放。每次这样的分配都将产生一个指针,指向一个与其他对象不相交的对象。返回的指针指向已分配空间的开始(最低字节地址)。如果无法分配空间,则返回空指针。如果请求的空间大小为零,则行为由实现定义:返回空指针以指示错误,或者行为就好像大小是某个非零值,除了返回的指针不应用于访问对象。所以,你的问题的基本前提是错误的,(成功)调用
malloc
所返回的指针将可用于 * 几乎任何 * 类型的对象,就对齐要求而言。对于有 * 扩展对齐 * 要求的对象,情况 * 可能 * 有所不同,在这种情况下,应该使用更具体的分配技术。