观侯捷老师new和delete以及malloc在vc当中调试模式和运行下分配内存

时间:2022-08-26 19:48:39

在讲到new和delete不得不想到c语言中的malloc and free 以及其经常用于动态内存分配,而简单来说,动态内存分配在堆中,不会因为离开作用域而删除,而栈中存储的一般为函数参数,返回值以及作用域下的local orient.

那我们可想而知的是,在函数中如果我创建指针,肯定为了不浪费内存,我们选择动态分配内存的方式,那么就是利用C++中的new或者c中的malloc,我们需要养成一个良好的习惯就是记得释放内存不然会造成memory leak,想必大家经常听过这个词,那这里是为什么会造成内存泄漏,假设我们在一个作用域比如

{
    char* p = new char[3];
}

此时我们创建了一个指向char型的指针p,但是p没有delete,这时候,一块在heap中创建的char数组依旧存在,而这个地址的别名p因为离开了作用域而无法访问,那么这块内存在整个操作系统中就是无法使用的部分。

所以在内存中,我们使用了new就得伴随着delete。

这时候我们知道p是一个local orient,那么我们还会有一种写法就是static,也就是静态对象或者说全局对象,这种对象在离开作用域时,是不会消失的,他会伴随着程序结束而终结。

{
    static int a = 3;
}
那么说到这里,我们也会去想知道new到底是怎么工作的,从我的上一篇博客里,我们知道创建一个complex对象需要2个double也就是8个字节,这时候比如有下列的程序
{
    complex* p = new complex(0,0);
}
这时候我们使用new创建了指向complex(0,0)对象的指针p,而new是先为complex对象分配内存,也就是malloc一个内存大小为sizeof(complex)的堆大小给p指针,然后再在这地址上调用complex的构造函数,创建complex对象。

同样的delete的工作过程正好相反,delete先调用了析构函数删除了complex对象,然后再delete掉p指针所指向的内存,这时候我们发现好像complex调用不调用析构函数好像没有什么影响,我直接delete掉p的内存,也不会有memory leak啊,相信很多人会这样想,侯捷老师在视频中也没有这么说,但是我的理解就是确实没有影响,但是是因为他是complex,没有指针进行动态分配内存,假设我分配了内存,一个char*指向了堆里的另外一个地方,操作系统会知道我这块内存有人用了,谁用的我也不知道了,delete已经把它干掉了,别问我。这样是不是就造成内存泄漏了,所以delete要先把对象析构掉,再delete释放内存。

那么讲了这么多new和delete我们未必知道new会new出多少内存出来,new一个complex就一定出现一个complex的大小吗?

观侯捷老师new和delete以及malloc在vc当中调试模式和运行下分配内存

从上图,我们可以看到malloc一个对象的时候,不仅仅只有这个对象的大小,还有在Debug mode下的Debug header在complex对象上面有8个内存单元,下有一个内存单元,然后有表示这块内存大小的最上端和最下端的2个cookis,通过计算发现其值为8+(4*8+4*1)+(4*2)为52 而在vc当中存储大小一般都为16的倍数,所以填充3个pad到64,这时候cookis记录下大小为60,最后4位为预留的4位,一般都是0,可以用来表示内存是不是已经分配出去,所以改为61表示已经分配出去64字节.

同样的在realise mode下,没有debug header,这时候complex为8字节,加上cookis的4*2个字节,正好是16,不用填充,修改cookis为11,表示已经分配出去。

观侯捷老师new和delete以及malloc在vc当中调试模式和运行下分配内存观侯捷老师new和delete以及malloc在vc当中调试模式和运行下分配内存

如果我们new了一个array 对象那么该怎么表示,那么在上述的一个对象上,我们必须给一个内存单元来记录这个数组里面有几个对象,所以算的其值后还会加上这个内存单元,但是这里我觉得我们更应该关注的是delete的时候,如果不加[]为什么会造成memory leak,如果单单使用一个delete,我们知道的是系统默认其只有一个对象,调用这个对象的析构函数,然后delete释放了这块cookis表示的内存,没问题,至少在系统看来是这样的,对于complex,从我上面对new和delete联想分析一下,确实没问题,也没有被标记使用的内存没有释放,ok,但是如果含有指针的对象,指针指向了heap里面的一块内存,那块内存没有释放的话,就是内存泄漏了,所以要加上[]以便系统识别,养成一个好习惯。