当前位置:编程学习 > C/C++ >>

探究OS的内存分配对齐策略

问题:
  我们在写程序的时候经常发现程序使用的内存往往比我们申请的多,为了优化程序的内存占用,搅尽脑汁想要优化内存占用,可是发现自己的代码也无从优化了,怎么办?现在我们把我们的焦点放到malloc上,毕竟我们向系统申请的内存都是通过它完成了,不了解他,也就不能彻底的优化内存占用。
来个小例子
//g++ -o malloc_addr_vec  mallc_addr_vec.cpp 编译
 2 #include<iostream>
 3 using namespace std;
 4 int main(int argc, char *argv[])
 5 {
 6     int malloc_size = atoi(argv[1]);
 7     char * malloc_char;
 8     for (size_t i = 0; i < 1024*1024; ++i) {
 9         malloc_char = new char[malloc_size];
10     }
11     while (1) {}//此时查看内存占用
12     return 0;
13 }

 本文的测试环境为Linux 64Bit ,使用G++编译为可执行文件后,使用不同的启动参数启动,使用top命令查看程序占用的内存,这里我们主要是看RES指标
RES  --  Resident size (kb)
The non-swapped physical memory a task has used. 
 
测试案例:
1.每次new 1 Byte   Do 1024*1024次
 ./malloc_addr_vec 1
启动程序后的内存占用
 
 \


内存消耗 32MB

 2.每次new 24 Byte  Do 1024*1024次

 ./malloc_addr_vec 24

 启动程序后的内存占用

  \


 

内存消耗32MB

 3.每次new 25 Byte   Do 1024*1024次

 ./malloc_addr_vec 25

启动程序后的内存占用  


 \

内存消耗48MB
 
  为什么我们每次new 1Byte 和每次 new 24Byte系统消耗的内存一样呢?,为什么每次new 25Byte和 每次new 24Byte占用的内存完全不同呢?
  不知道大家在写程序的时候有没有关注过这个问题。我一次遇到时,吐槽一句:What the fuck malloc.

原因分析:
   在大多数情况下,编译器和C库透明地帮你处理对齐问题。POSIX 标明了通过malloc( ), calloc( ), 和 realloc( ) 返回的地址对于任何的C类型来说都是对齐的。
  对齐参数(MALLOC_ALIGNMENT) 大小的设定并需满足两个特性
 1.必须是2的幂
 2.必须是(void *)的整数倍
  至于为什么会要求是(void *)的整数倍,这个目前我还不太清楚,等你来发现...
  根据这个原理,在32位和64位的对齐单位分别为8字节和16字节
  但是这并解释不了上面的测试结果,这是因为系统malloc分配的最小单位(MINSIZE)并不是对齐单位
 为了进一步了解细节,从GNU网站中把glibc源码下载下来,查看其 malloc.c文件
  View Code
 1 #ifndef INTERNAL_SIZE_T 
 2 #define INTERNAL_SIZE_T size_t 
 3 #endif 
 4 #define SIZE_SZ                (sizeof(INTERNAL_SIZE_T)) 
 5 #ifndef MALLOC_ALIGNMENT 
 6 #define MALLOC_ALIGNMENT       (2 * SIZE_SZ) 
 7 #endif 
 8
 9
10 struct malloc_chunk { 
11   INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */ 
12   INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */ 
13   struct malloc_chunk* fd;         /* double links -- used only if free. */ 
14   struct malloc_chunk* bk; 
15 }; 
16
17     An allocated chunk looks like this: 
18     chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
19             |             Size of previous chunk, if allocated            | | 
20             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
21             |             Size of chunk, in bytes                       |M|P| 
22       mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
23             |             User data starts here...                          . 
24             .                                                               . 
25             .             (malloc_usable_size() bytes)                      . 
26             .                                                               | 
27 nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
28             |             Size of chunk                                     | 
29             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
30            
31            
32 #define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1) 
33 #define MIN_CHUNK_SIZE        (sizeof(struct malloc_chunk)) 
34 #define MINSIZE  / 
35   (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) 
36 /* pad request bytes into a usable size -- internal version */ 
37 #define request2size(req)                   &nbs

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,