C中内存堆栈的布局---linux 简单实例

来源:互联网 发布:淘宝app怎么看评价 编辑:程序博客网 时间:2024/05/22 14:42

http://blog.csdn.net/billvsme/article/details/18282897


一、linux 内存管理 

1.   变量空间

linux 每运行一个程序都会在/proc内生成一个跟自己pid一样的文件夹,你面放着程序有关的信息


ldd ./1

可以看到

linux-vdso.so.1 (0x00007fff47eac000)
libc.so.6 => /lib64/libc.so.6 (0x00007f37c4414000)
/lib64/ld-linux-x86-64.so.2 (0x00007f37c47bc000)

/lib64/ld-linux-x86-64.so.2是一个可执行文件 用来生成 /proc/${pid}内的文件



[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">#include<stdio.h>  
  2. #include<unistd.h>  
  3. #include<malloc.h>  
  4. int a1;  
  5. static int a2=2;  
  6. const int a3=2;  
  7. int add(int a,int b)  
  8. {  
  9.     return a+b;  
  10. }  
  11. int main()  
  12. {  
  13.   
  14.     int b1;  
  15.     static int b2=2;  
  16.     const int b3=2;  
  17.     int *p1;  
  18.     int *p2 = (int *)malloc(4);  
  19.     printf("a1 %p\n",&a1);  
  20.     printf("a2 %p\n",&a2);  
  21.     printf("a3 %p\n",&a3);  
  22.     printf("b1 %p\n",&b1);  
  23.     printf("b2 %p\n",&b2);  
  24.     printf("b3 %p\n",&b3);  
  25.     printf("p1 %p\n",p1);  
  26.     printf("p2 %p\n",p2);  
  27.     printf("main %p\n",main);  
  28.     printf("f %p\n",add);  
  29.     printf("%d\n",getpid());  
  30.     while(1);  
  31.     return 0;  
  32. }</span><span style="font-size: 18px;">  
  33. </span>  

结果

a1 0x601060
a2 0x601048
a3 0x400828
b1 0x7fffaa41f41c
b2 0x60104c
b3 0x7fffaa41f418
p1 0x7fffaa41f510
p2 0xddd010
main 0x4005e8
f 0x4005d4
18155


cat /proc/18155/map 结果


00400000-00401000 r-xp 00000000 08:13 1845721                            /codes/gj/1
00600000-00601000 r--p 00000000 08:13 1845721                            /codes/gj/1
00601000-00602000 rw-p 00001000 08:13 1845721                            /codes/gj/1
00ddd000-00dfe000 rw-p 00000000 00:00 0                                  [heap]
7f7916efa000-7f7917099000 r-xp 00000000 08:13 2883641                    /lib64/libc-2.15.so
7f7917099000-7f7917298000 ---p 0019f000 08:13 2883641                    /lib64/libc-2.15.so
7f7917298000-7f791729c000 r--p 0019e000 08:13 2883641                    /lib64/libc-2.15.so
7f791729c000-7f791729e000 rw-p 001a2000 08:13 2883641                    /lib64/libc-2.15.so
7f791729e000-7f79172a2000 rw-p 00000000 00:00 0 
7f79172a2000-7f79172c3000 r-xp 00000000 08:13 2883719                    /lib64/ld-2.15.so
7f7917490000-7f7917493000 rw-p 00000000 00:00 0 
7f79174c1000-7f79174c3000 rw-p 00000000 00:00 0 
7f79174c3000-7f79174c4000 r--p 00021000 08:13 2883719                    /lib64/ld-2.15.so
7f79174c4000-7f79174c5000 rw-p 00022000 08:13 2883719                    /lib64/ld-2.15.so
7f79174c5000-7f79174c6000 rw-p 00000000 00:00 0 
7fffaa400000-7fffaa421000 rw-p 00000000 00:00 0                          [stack]
7fffaa444000-7fffaa445000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


可以知道  全局的 普通变量、静态变量放在 全局栈中,全局 const变量 放在 代码区 。

                局部普通变量 和const变量都放在局部栈中,static变量放在 全局栈中。malloc申请的空间放在 堆中。

                main函数 和 自己写的函数 都是放在 代码区的。


2.malloc 申请的内存

[cpp] view plaincopy
  1. <span style="font-size:14px;">#include<stdio.h>  
  2. #include<unistd.h>  
  3. #include <malloc.h>  
  4.   
  5. int main(int argc, const char *argv[])  
  6. {  
  7.     int a1 = 10;  
  8.     int a2 = 10;  
  9.     int a3 = 10;  
  10.   
  11.     int *p1 = (int*)malloc(4);  
  12.     int *p2 = (int*)malloc(4);  
  13.     int *p3 = (int*)malloc(4);  
  14.   
  15.     printf("a1 %p\n",&a1);  
  16.     printf("a2 %p\n",&a2);  
  17.     printf("a3 %p\n",&a3);  
  18.   
  19.     printf("p1 %p\n",p1);  
  20.     printf("p2 %p\n",p2);  
  21.     printf("p3 %p\n",p3);  
  22.   
  23.   
  24.     printf("%d\n",getpid());  
  25.     while(1);  
  26.     return 0;  
  27. }  
  28.   
  29.   
  30. 结果:  
  31. a1 0x7fff4445f7a4  
  32. a2 0x7fff4445f7a0  
  33. a3 0x7fff4445f79c  
  34. p1 0x1dcb010  
  35. p2 0x1dcb030  
  36. p3 0x1dcb050  
  37. 18323</span>  


可以知道:
1. 普通变量是在栈中的,它的地址是 越早分配的地址越小,malloc 创建的内存是在堆中的地址是按顺序分配下来的
2. malloc申请的变量不是申请4个字节就只占用4个直接,具体见后面。


3.malloc申请的内存结构

[cpp] view plaincopy
  1. <span style="font-size:14px;">#include<stdio.h>  
  2. #include<malloc.h>  
  3.   
  4. int main(int argc, const char *argv[])  
  5. {  
  6.     int *p1 = malloc(4);  
  7.     int *p2 = malloc(4);  
  8.     int *p3 = malloc(4);  
  9.     *p1 = 1;  
  10.     *(p1+1) = 2;  
  11.     *(p1+2) = 3;  
  12.     *(p1+3) = 4;  
  13.     *(p1+4) = 5;  
  14.     *(p1+5) = 6;  
  15.     *(p1+6) = 7;  
  16.     *(p1+7) = 8;  
  17.     *(p1+8) = 10;  
  18.     *(p1+9) = 11;  
  19.   
  20.     //free(p1);  
  21.     printf("%d\n",*p2);  
  22.     return 0;  
  23. }  
  24. 结果:  
  25. 10</span>  



虽然看起来没有什么错,但如果 free(p1)就会出现严重的错误。
原因   堆是由链表管理的,malloc 生成的空间 , 先是本身的数据,再是前一个元素的地址,再是后一个元素的地址,再后一个是本身数据的长度。所以改变 p1+2 p1+3 的值会使 free 出错。


4.new delete跟 malloc free有什么区别

new就是靠malloc的 delete 就是靠free的,
只是new 在生成是会初始化,delete在删除是会先清0。


其他知识点:

c语言是弱类型语言,c++是强类型语言
int *p = malloc(4);
在c是对的,在c++是错的,c++一定要(int*)malloc(4);
gcc xxx.cpp 是按照c++ 编译的
gcc xxx.c     才会按照c编译
0 0
原创粉丝点击