【转自】https://blog.csdn.net/One_L_Star/article/details/81901186
从逻辑层面(操作系统)把数据分成不同的段(不同的区域)来存储:
一、代码段(codesegment/textsegment):
- 又称文本段,用来存放指令,运行代码的一块内存空间
- 此空间大小在代码运行前就已经确定
- 内存空间一般属于只读,某些架构的代码也允许可写
- 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
二、数据段(datasegment):
- 可读可写
- 存储初始化的全局变量和初始化的static变量
- 数据段中数据的生存期是随程序持续性(随进程持续性)
随进程持续性:进程创建就存在,进程死亡就消失
三、bss段(bsssegment):
- 可读可写
- 存储未初始化的全局变量和未初始化的static变量
- bss段中数据的生存期随进程持续性
- bss段中的数据一般默认为0
四、rodata段:
- 只读数据
- 比如printf语句中的格式字符串和开关语句的跳转表。也就是你所说的常量区。例如,全局作用域中的 const int ival = 10,ival存放在.rodata段;再如,函数局部作用域中的printf("Hello world %d ", c);语句中的格式字符串"Hello world %d ",也存放在.rodata段。
五、栈(stack):
- 可读可写
- 存存储的是函数或代码码中的局部变量(非static变量)
- 栈的生存期随代码块持续性,代码块运行就给你分配空间,代码块结束,就自动回收空间
六、堆(heap):
- 可读可写
- 存储的是程序运行期间动态分配的 malloc/realloc的空间
- 堆的生存期随进程持续性,从malloc/realloc 到free一直存在
进程地址空间和用户、内核的关系:
eg:前辈写的一个经典例子
int a = 0; //全局初始化区 char *p1; //全局未初始化区 main() { int b; //栈 char s[] = "abc"; //栈 char *p2; //栈 char *p3 = "123456"; //123456 在常量区,p3的栈上 static int c = 0; //全局(静态)初始化区 p1 = (char*)malloc(10); p2 = (char*)malloc(20); //分配得来的10和20字节的区域就在堆区 strcpy(p1,"123456"); //123456 放在常量区,编译器可能会将它与p3所指向“123456”优化成一个地方 }