本文主要是介绍malloc(malloc在32位编译系统中分配的地址会8字节对齐,64为编译系统中会8或者16字节对齐),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
了解malloc分配策略的人都知道,malloc在32位编译系统中会8字节对齐,64为编译系统中会8或者16字节对齐。
故32位malloc分配后的首地址肯定是8的整数倍。
举例说明:
32位系统环境, 假设按4字节对齐,分配8字节的存储空间存储long long型的内容。
malloc获取地址为0x1acf3014(4字节对齐), 返回给用户的地址为0x1acf300c(实际存储数据的地址), 如果long long
型的数据放入这个地址,由于__alignof__(long long)=8,要求8字节对齐。所以该数据由于内存未对齐访问效率低下,甚
至访问出错。
如果在32位系统自己实现的malloc函数空间不按照8字节对齐,会产生问题(如果自己实现的malloc函数返回的是4字节对齐的内存地址,比如0x0000000c,而分配的此首地址0x0000000c不能被8整除,但是我要在0x0000000c-0x00000014 放置longlong 8个字节的变量类型就会出现问题),此问题会类似我的另一篇文章如果指定在不能被4整除的内存地址上放置int型变量会发生什么。
至于什么是内存对齐、为什么要做内存对齐,这涉及到计算机体系结构相关知识。已经有很多前辈写了许多关于内存对齐的相关文章,如果感兴趣可以google。
malloc的相关源代码如下:
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
/* The corresponding word size */
#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
#ifndef MALLOC_ALIGNMENT
/* #define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) \
? __alignof__ (long double) : 2 * SIZE_SZ)
*/
#define MALLOC_ALIGNMENT (2 * SIZE_SZ)
#endif
MALLOC_ALIGNMENT 就是malloc的最小对齐参数,也是研究的重点。那这里为什么要2*SIZE_SZ对齐呢?
其实上面红色字体才是MALLOC_ALIGNMENT宏的正确定义。 只是这样定义会带来一些兼容性的问题,故而采用
2*SIZE_SZ定义(对于大多数平台这种定义也是正确的), 看来这里只是想表示最大元类型的字节数的意思。我们
知道元类型、结构类型等都是要作内存对齐的(主要是从寻址和访问效率上考虑)。那么我们在采用动态内存分配的
时候也要保证存储的数据是内存对齐的。但malloc分配内存的时候不知道内存的用途。所以就只有按最大元类型对齐。
举例说明:
32位系统环境, 假设按4字节对齐,分配8字节的存储空间存储long long型的内容。
malloc获取地址为0x1acf3014(4字节对齐), 返回给用户的地址为0x1acf300c(实际存储数据的地址), 如果long long
型的数据放入这个地址,由于__alignof__(long long)=8,要求8字节对齐。所以该数据由于内存未对齐访问效率低下,甚
至访问出错。
动态分配内存对齐一般是按系统最大元类型的对齐要求来对齐内存的。 这个值就是最小的对齐参数。小于这个值就会出
现内存无法对齐的现象。 当然选择比这个值大是没有问题的(比如16)。
以上是我个人的理解,如有错误,欢迎批评指正。
这篇关于malloc(malloc在32位编译系统中分配的地址会8字节对齐,64为编译系统中会8或者16字节对齐)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!