内存new & delete
Stack&Heap
stack
stack是存在于某作用域(scope)的一块内存空间(memory space)。在函数本体内声明的任何变量,其所使用的内存块都取自stack。例如当你调用函数,函数本身即会形成一个stack用来放置它所接收的参数,以及返回地址。
stack 所谓的stack object,
- auto object,其生命在作用域结束之际结束,因为他会被自动清理
- static object,其生命在作用域结束之后仍然存在,直到整个程序结束
- global object,其生命在整个程序结束之后才结束,也可以视为一种static object,其作用域为整个程序
Heap
Heap(system heap)是指由操作系统提供的一块global内存空间,程序可动态分配(dynamic allocated),从其中获得若干区块(blocks),
- heap object,其生命周期在被delete之后结束。程序作用域内需要自己delete,因为当作用域结束,heap objec仍然存在,但指针的生命却结束了,作用域外之后将看不见就没机会delete,造成内存泄漏
对象创建
对象new & delete 过程
new:先分配memory,再调用ctor
Complex* pComplex = new Complex(1, 2);
1. void *pComplex = operator new(sizeof(Complex))=>内部调用malloc(sizeof(Complex)) //分配内存
2. pComplex =static_cast<Complex*>(pComplex ); //转型
3. pComplex ->Complex::Complex(1,2) => Complex::Complex(pc,1,2); //构造函数
delete:先调用dtor,再调用delete
delete pComplex;
1. Complex ::~Complex (pComplex) //析构函数
2. operator delete(pComplex)=>内部调用free(ps) //释放内存
内存分配
object new & delete
- 每个格子为4个字节,左边为debug,右边为release
- 深绿色 申请内存
- 浅灰色 调试内存
- 深灰色 CooKie _记录整块申请的大小,melloc/free的时候使用,
- 浅绿色 字节对齐
- Complex * pc=new Complex(1,2) ; //两个double
- debug
8+(32+4)+(4+4)=52=>64(字节对齐,16倍数)
十六进制下00000041,用最后一位0/1标识是melloc/free - release
8+(4+4)=16
- debug
- String* ps=new String(“Hello”); //一个string指针
- debug
4+(32+4)+(4+4)=48 - release
4+(4+4)=12=>16
- debug
array object new & delete
array new
m_data = new char[ strlen(str.m_data) + 1 ];
delete[] m_data;
-
每个格子为4个字节,左边为debug,右边为release
- 深绿色 申请内存
- 浅灰色 调试内存
- 深灰色 CooKie(记录整块申请的大小,melloc/free使用)
- 白色 记录数组大小(int)
- 浅绿色 字节对齐
-
Complex * pc=new Complex[3] ; //两个double*3
- debug
(8*3)+(32+4)+(4+4)+4=72=>80 - release
(8*3)+(4+4)+4=36=>48
- debug
-
String* ps=new String[3]; //一个string指针*3
- debug
(4*3)+(32+4)+(4+4)+4=60=>64 - release
(4*3)+(4+4)+4=24=>32
- debug
array delete
-
左边:delete
- delete[] 编译器知道有三块,调用3次析构函数
- 利用CooKie完整删除整块
-
右边:delete
- delete 编译器以为只有一块,调用析构1次,第二块和第三块造成内存泄漏
- 利用CooKie完整删除整块