众所周知,一个进程在内存中的空间分为三部分:Text(Code) Segment, Data Segment,Stack Segment。
不知道哪个BT非要把“Stack”译为“堆栈”,真是害人不浅。这三部分的中文名称应为:代码段、数据段、栈段。
对于Linux下的C程序而言,数据段又可分为三个区域:Initialized data、Zero-initialized data(BSS)、Heap。因而整个进程空间分为以下5部分:
Code:代码段,存放可执行程序
Initialized data:初始化为非0的全局变量或静态变量存放在该区域
Zero-initialized data:也叫BSS区(Block Started by Symbol)。初始化为0的全局变量或静态变量存放在
该区域,由于C语言规定:未复初值的变量默认值都为0,所以不管是显示初始化
为0的全局变量和静态变量,还是未赋值的全局变量和静态变量都存放在该区域。
Heap:堆区域,用malloc、calloc等分配的空间就存在于此区域中。
Stack:栈,存放未用satic声明的局部变量
五个区域在内存中的位置如下图所示:
数据段这一部分变量的分配总是从低地址到高地址,而栈的分配则是从高地址到低地址。
下面这个C程序可以很好的说明问题(运行在linux CentOS 64位系统下)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int data_var1 = 1;
int bss_var1 = 0;
int bss_var2;main()
{
int stack_var1;
int stack_var2;
static int data_var2 = 1;printf("Data Locations:/n");
printf("/tAddress of data_var1: %p/n", &data_var1);
printf("/tAddress of data_var2: %p/n", &data_var2);printf("BSS Locations:/n");
printf("/tAddress of bss_var1: %p/n", &bss_var1);
printf("/tAddress of bss_var2: %p/n", &bss_var2);
printf("Heap Locations:/n");
char *heap_p1 = NULL, *heap_p2 = NULL;
heap_p1 = sbrk((intptr_t) 32);
heap_p2 = sbrk((intptr_t) 0);printf("/tInitial heap end: %p/n", heap_p1);
printf("/tNew heap end: %p/n", heap_p2);
heap_p1 = sbrk((intptr_t) -16);
heap_p2 = sbrk((intptr_t) 0);
printf("/tNew head end: %p/n", heap_p2);
printf("Stack Locations:/n");
printf("/tAddress of stack_arg1: %p/n", &stack_var1);
printf("/tAddress of stack_arg2: %p/n", &stack_var2);
}
运行结果:
Data Locations:
Address of data_var1: 0x600b20
Address of data_var2: 0x600b24
BSS Locations:
Address of bss_var1: 0x600b2c
Address of bss_var2: 0x600b30
Heap Locations:
Initial heap end: 0x1672a000
New heap end: 0x1672a020
New head end: 0x1672a010
Stack Locations:
Address of stack_arg1: 0x7fffd779c04c
Address of stack_arg2: 0x7fffd779c048