C/C++编译的程序占用的内存分为以下几个部分:
.stack .heap .data. .bss .text
- 栈区(stack): 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈
- 堆区(heap) : 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
- 全局区(静态存储区)(static): 全局变量和静态变量的存储是放在一块的,a .初始化的全局变量和静态变量在一块区域(.data段), b .未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss段)。程序结束后有系统释放
- 文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
- 代码区—存放函数体的二进制代码。
我们将文字常量区和代码区视为一个部分,即代码区
#include
#include
int a = 1234; //全局区
int main()
{
char *b = "Hello!~~"; // 栈区,指针指向代码区,b变量本身也在栈区
int c = 5678; // 栈区
int *d = (int*)malloc( sizeof(int) ); //堆区,指针指向堆区,d变量本身同样在栈区
*d = 9999;
static char e = 0; //全局区
static int (*f)() = main; //指向代码区,f本身在全局区
printf( "&a = %08x, a = %d\n", &a, a );
printf( " b = %08x, b = %s, &b = %08x\n", b, b, &b );
printf( "&c = %08x, c = %d\n", &c, c );
printf( " d = %08x, *d = %d, &d = %08x\n", &d, *d, &d );
printf( "&e = %08x, e = %d\n", &e, e );
printf( "&f = %08x, f = %d\n", &f, f );
printf( "&main = %08x, main = %d\n", &main, main );
return 0;
}
.stack 栈区,用来存放局部变量,函数的参数,返回值等,
栈中的内存是操作系统自动分配的, 也由编译器自动分配释放;
栈的概念来自数据结构,栈只能在一端操作,所以先入栈的后出,“先进后出”,这种结构保护之前的现场, 如一个函数被调用后,产生的临时变量都会存到栈区的顶部,当函数完成后,会自动从顶部将刚使用的数据销毁;
栈区的地址是从高地址向下增长的;
栈通俗点说是由寄存器ebp和esp指向的一个空间。用于存放临时的数据。符合先进后出原则。适用于函数的临时变量以及返回值
esp是栈顶指针寄存器,ebp是栈底指针寄存器。
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶(下一个压入栈的活动记录的顶部),是栈指针。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部(当前活动记录的底部),是帧指针。
void foo(){ // 栈区 }
int main(){ // 栈区 }
.heap 堆区,用来动态内存分配,如malloc, new申请的内存,由程序员分配释放;
(1)堆中的内存分配是因为我们new/malloc空间的时候,申请的空间的大小不一样造成了碎片。使用malloc的时候系统内部有一个空闲内存映射表,系统会自动查找空闲内存中的第一个合适大小的空间分配
(2)每一次分配的内存是连续的,但如果用结构体链表来管理分配的内存就可以将每一次分配的内存虚拟的连接起来,但前提是每一次分配的内存还是连续的,只是每个节点所占的内存单元不是连续的
堆区使用时地址向上增长;
char* arr = (char*) malloc(sizeof(buf) * sizeof(10));
free(arr)
char* c = new char('a');
delete c;
char* arr = new char[15];
delete arr[];
全局变量和静态变量存放在此,分为两个段:DATA段和BSS段,该区域是在程序结束后由操作系统释放.
.DATA段:存放初始化的全局变量,(全局和局部)静态变量,常量只初始化一次;
.BSS段:存放未初始化的数据(全局变量和静态变量),用0来初始化
ANSI 定义数组时 int a[10], 定义中的长度为常量,
但是 const int m = 10; int a[m];是错误的
因为虽然 m定义为常整型变量,却任然是变量,存储在内存的只读区中,不可修改
.Text 这个区域存放函数体的二进制代码.也是由操作系统进行管理的
.stack | 栈区 高---->低 |
---|---|
.heap | 堆区 低---->高 |
.bss | 未初始化全局区 |
.data | 初始化全局区 |
.text | 代码区 |
C语言程序中,根据是局部变量,全局变量, 常量还是通过malloc等类似的函数分配内存空间, 把他们放到对应的内存区中.这样就赋予了这些变量或常量不同的生命周期, 不同的释放方式. 根据我们程序的需要,我们在编码过程中,声明不同的变量类型, 使他们有不同的声明长度, 不同的释放方式,给我们更大的灵活编程
text, data and bss: 代码和数据的所占空间详解