我们把一个C++程序在运行的时候所占据的内存空间,分成四个部分
栈区
堆区
全局区/静态区
常量区
在C++程序的内存空间中,我们在代码中声明的局部变量,以及函数的形式参数,都保存在栈区中,这部分内存在程序运行的时候会自动分配,而在不需要的时候也会自动释放,并不需要去手动维护
而我们使用new或者malloc函数进行动态内存分配后,系统为我们划分的内存空间,就来自于堆区,因为程序自己不知道这些动态内存到什么时候会派不上用场,所以程序并不会对这部分分配的内存做任何处理
如果不及时使用new或delete运算符的话,会造成内存泄漏
存储规则:
假设程序内存地址从0x0000开始,到0xFFFF结束,我们可以看到随着存储内容的增大,堆会从低地址开始到高地址结束,
栈则相反,如果内存空间用完的话,则会发生segment fault,就是段错误
具体案例:
int myFunc2(){
int *p=new int[2]; //p是局部变量,保存在栈区,而p指向的具有两个元素的数组,作为一个堆对象而位于堆区中,不要把指针变量和指针所指变量搞混了
}
p是指针局部变量,保存在栈区,而指向的两个元素数组,作为一个堆对象位于堆区中
切记不要搞错
还有要注意深复制的影响:
#include <iostream>
using namespace std;
struct Point
{
int x;
int y;
};
int main() {
Point a{ 1,2 };
Point b = a;
Point *c = new Point{ 3,4 };
Point *d = c;
a.x = 10;
c->x = 10;
cout << b.x << " " << d->x << endl;
system("PAUSE");
}
因为c和d在这里共享了一个地址,所以会发生深复制,即使给c赋值也会造成d发生同样的赋值,因为他们共享了一个地址
检测方法:在在cpp文件处进行预定义
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h> //头文件
#include <crtdbg.h>
#define NEW_WITH_MEMORY_LEAK_CHECKING new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new NEW_WITH_MEMORY_LEAK_CHECKING
程序运行完毕:定义以下函数
_CrtDumpMemoryLeaks();