一:一个C/C++程序编译之后在内存中一般分为五个部分
1. 程序代码区:程序代码区主要用来存放程序执行代码,包括类成员函数、全局函数、静态函数等其它函数的代码。这部分内存区域的大小在程序运行前就已经确定了,并且内存通常是只读的。一般程序代码区是可以被共享的
2. 常量区:用来存放常量的内存区域,程序结束后由操作系统收回
3. 全局数据区(静态存储区):存放全局变量和静态变量,程序结束后由操作系统收回。
全局变量、静态全局变量、静态局部变量都是在静态存储区分配空间的。
4. 堆区:堆用于存放程序运行中动态分配的内存段,它的大小不是固定的,可以动态的扩张和缩减。
当进程调用new或malloc申请内存空间的时候,堆被扩张;当使用delete或free释放内存空间的时候,堆被缩减。
堆一般由程序员手动分配和释放,如果没有释放则会在程序结束的时候由操作系统收回。
堆的内存分配机制如下:操作系统有一个专门用来存储空闲内存地址的链表,链表每个结点表示一块空闲内存地址空间。当程序收到new或malloc申请时,就去查找这个链表直到找到一个结点的内存空间大于所申请的内存空间,将这个结点从链表中删除并将内存分配给程序,如果有剩余的内存空间则继续放入到链表中使用。
堆区不是连续的内存空间因为系统用链表来存储空闲内存地址,堆的内存空间相对较大,在windows下堆申请的空间一般超过2G。
5. 栈区:栈区主要用来存储程序临时创建的局部变量,包括函数体内的局部变量、函数参数等。(但是不包括静态局部变量因为所有的静态变量存放在全局数据区)
栈由编译器自动分配和释放,操作形式类似数据结构的栈,效率比较高,但是栈能够分配的大小是固定的一般比较小。
栈是一块连续的内存区域,栈顶的地址和栈的容量是预先规定好的,windows下栈的大小是2M。
二:堆区是由低地址向高地址生长,栈是由高地址向低地址生长
举例:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int global = 5; //全局数据区 static int value = 3; //全局数据区 int main(){ int a; //栈区 char str[] = "abc"; //str存放在栈区 char *p = str; //栈区 static int c = 0; //全局数据区 char *p1; p1 = (char *)malloc(5*sizeof(char)); //堆区 p1 = "1234"; //"1234"存放在常量区 return 0; }
三:内存泄露
1. 堆是动态分配内存的,可以分配比较大的内存空间,因此使用不好容易造成内存泄露和内存碎片
2. 内存泄露一般是指堆内存的泄露,指的是由于疏忽或错误造成程序未能释放已经不再使用的内存空间,造成这些内存空间不受控制造成内存浪费