C语言程序内存布局
系统内核(kernel)
|
栈区(stack)
|
缓冲区
|
堆区(heap)
|
BSS段
|
数据段(data)
|
代码区(text) |
1、代码区:程序(函数)代码所在,由编译而得到的二进制代码被载入至此,代码区是只读的!有执行权限。值得注意的是,字符串字面值常量就存储在这个区。
2、数据段和BSS段:合称静态区(全局区),用来存储静态(全局)变量。区别是前者(数据段)存储的是已初始化的静态(全局)变量,可读写;后者(BSS段)存储的是未初始化的静态(全局)变量,可读写。
3、堆区:自由存储区。不像全局变量和局部变量的生命周期被严格定义。堆区的内存分配和释放是由程序员所控制的。申请方式:C中是malloc函数,C++中是new标识符。
4、栈区:由系统自动分配和释放。存储局部(自动)变量,一般说的堆栈,其实是指栈!另外,值得注意的是,堆是由低地址向高地址分配空间;栈却是由高地址向低地址分配空间。
通过下面一段代码认识一些内存布局:
#include <stdio.h> #include <stdlib.h> int x = 10; //静态全局区(data段) int y; //静态全局区(bss段) static int m = 20; //静态全局区(data段) const int n = 30; //代码区!! void fun(int i){ //stack int i1 = 50; //stack static int i2 = 60; //静态全局区(data段) const int i3 = 70; //栈区!! char *str1 = "Hello world!"; //代码区(字符串常量) char str2[] = "abcdefg"; //栈区(字符数组) int *pt = malloc(sizeof(int)); //堆区 printf("Address of i: %p\n", &i); printf("Address of i1: %p\n", &i1); printf("Address of i2: %p\n", &i2); printf("Address of i3: %p\n", &i3); printf("Address of str1: %p\n", str1); printf("Address of str2: %p\n", str2); printf("Address of pt: %p\n", pt); free(pt); } int main(){ printf("Address of x: %p\n", &x); printf("Address of y: %p\n", &y); printf("Address of m: %p\n", &m); printf("Address of n: %p\n", &n); fun(50); return 0; }
运行结果如下:
$ ./a.out
Address of x: 0x804a028
Address of y: 0x804a038
Address of m: 0x804a02c
Address of n: 0x80486c0
Address of i: 0xbfab1f60
Address of i1: 0xbfab1f34
Address of i2: 0x804a030
Address of i3: 0xbfab1f38
Address of str1: 0x80486c4
Address of str2: 0xbfab1f44
Address of pt: 0x8bd2410
从上面代码运行结果可以看出x、y、m、i2都是同在静态全局区,i、i1、i3、str2都是栈区,n和str1都属于代码区,而pt属于堆区。值得注意的是,代码区通常情况下都是只读,试图修改代码区会引发段错误。