内存布局
text
:代码段,存放程序的二进制代码
、字面量(整数常量
、浮点常量
、字符常量
、字符串字面值
、枚举常量
),该区域的大小在编译期间即可确定,在运行期间通常是只读的;data
:存放已初始化且初始值非零的静态变量的全局数据段,静态变量在进程启动时被依次赋值,在进程结束时被系统释放,该区域的大小在编译期间即可确定,在运行期间是可读写的,但是整个 data 段的大小是固定的;bss
:存放未初始化或初始值为零的静态变量的全局数据段,进程启动时会将该区域全部赋予 0 值,在进程结束时被系统释放,该区域的大小在编译期间即可确定,在运行期间是可读写的,但是整个 bss 段的大小是固定的;heap
:堆区,存放进程在运行期间动态申请的内存段,大小是不固定的,可动态扩张和缩减,使用 malloc 等函数分配的内存就在堆上,使用完后可以使用 free 函数来主动释放申请的内存,如果不释放,则在进程结束时被系统自动释放;stack
:栈区,存放函数的局部变量、函数的参数等值,每个函数栈帧的大小在编译期间是确定的,但是整个栈区的大小是不定的,不过操作系统对于每个栈的大小是有限制的,在 Linux 中一般为 8192 KB,也就是 8 MB,如果需要可以适当调高(使用 ulimit 命令)。
在多线程环境中:
text
、data
、bss
、heap
都是线程间共享的,如果对该区域的数据的访问顺序敏感,则需要采取相应的措施,如使用互斥锁,来避免出现脏数据问题;stack
是每个线程私有的,每个线程都会有一个独立的 stack 区域,每个 stack 区域都拥有一样的大小限制(即操作系统对栈的大小限制)。
实例说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i1; // 变量 i1 位于 bss
int i2 = 0; // 变量 i2 位于 bss
char ch = 'A'; // 变量 ch 位于 data,值 'A' 位于 text
// 变量 str1 位于 data,值 "www.zfl9.com\0" 位于 text
char *str1 = "www.zfl9.com";
// 变量 str2 位于 data,值 "www.zfl9.com\0" 位于 text (与 str1 指向的是同一个字符串)
char *str2 = "www.zfl9.com";
int main(void) {
static int st_i; // 变量 st_i 位于 bss
static char st_c = 'X'; // 变量 st_c 位于 data,值 'X' 位于 text
int au_i; // 变量 au_i 位于 stack
// 变量 str3 位于 stack,分配的内存位于 heap
char *str3 = (char *)malloc(sizeof(char) * 20);
// 变量 str4 位于 stack,值 "www.google.com\0" 位于 text
char *str4 = "www.google.com";
// "www.google.com\0" 位于 text,并且与 str4 指向的是同一个字符串
strcpy(str3, "www.google.com");
free(str3);
return 0;
}