一、C/C++内存分配
C++内存分段:
- 代码区—— .text,代码存放的区域
- 常量存储区—— .data,包括了常量,不允许修改,否则发生段错误
- 全局区/静态区—— .bss,也称为零段,全局变量和静态变量存储的区域,如果没有赋初值则初值为0.
- 堆—— 程序员可支配的区域,使用malloc、new定义的变量存储在此区域。
- 栈—— 包括了局部变量、函数等。
对于C语言而言,初始化的全局变量放在.data段,而未初始化的全局变量放在.bss段。
二、程序和进程
程序是静态的,运行起来就成为进程。比如一段代码main.c,你在里面定义了一堆局部变量、malloc开辟出了一些空间,但是在未运行的时候只有常量、全局/静态变量才需要开辟空间存储。因此定义在堆栈区的变量、函数等并不会占据程序的空间,但是如果程序有太多的全局变量,就会导致程序很大,运行很慢,所以不推荐使用太多的全局变量。
将main.c编译链接后,生成可以执行文件,运行可执行文件就是一个进程了。进程将原程序的内容拷贝后,并增加了堆、栈、共享内存(和其他进程共享的区域)。当然,因为链接不管是静态链接还是动态链接都有其他大量的信息和相关的内容,所以实际代码还有其他段。
三、查看内存分段
在linux下,运行相应的指令可以轻松地看出内存的分区。
3.1 创建文件
输入指令:gedit text.c,在窗口中书写一段C语言代码。
3.2 编译文件
输入指令:gcc -c text.c编译文件后,通过ls可以看到生成了一个text.o文件
3.3 查看内存
输入指令:objdump -h text.o查看内存分区。由3.1可知,我们定义了一个初始化过后的全局int型变量len,发现.data段刚好是4个字节,也就是一个int型变量len。
3.4 修改
gedit text.c
gcc -c text.c
objdump -h text.o
根据前面的三个步骤,添加一句新的代码printf(“hello\n”);后编译。
这时候查看内存,发现.rodata从0变为6。因为字符串"hello"存放在常量区,5个字节再加上’\n’刚好是6个字节。可见,.rodata是常量区,用于存放const修饰的常量或字符串。