C++: delete与内存泄露

在C++中可以方便地通过运算符new和delete来动态分配内存,其中new的默认语义是分配内存并调用构造函数,而delete的默认语义是调用析构函数并释放内存,需要注意的是这两个运算符都和指针打交道,而涉及到指针事情就有点复杂了,来看一个例子:

class A {
	public:
	~A() { cout<<"destructor of A"<<endl; }
};

class B : public A {
	public:
	~B() { cout<<"destructor of B"<<endl; }
};

int main(){

	A *p = new B();
	delete p;

	return 0;
}

在这个例子中,B继承于A,所以A的指针可以指向B,在main()中我们动态创建了一个B的对象,并用一个A的指针来指向它,当我们不需要这个对象时,理应调用B的析构函数并释放掉相应的内存,所以直接就 delete p 了,那么输出结果呢?

destructor of A;

只有A的析构函数被调用了,所以如果我们在B的析构函数中有一些释放内存的操作,那么这些释放内存的操作不会被执行,从而引发内存泄露,导致这个问题的原因在于编译器认为delete后面跟的是静态指针,所以它会根据p的类型来在编译期确定哪个析构函数被调用,在此例中,p是A类型的指针,所以A的析构函数被调用。避免这个问题的方法是使用虚析构函数,如下:

#include <iostream>
using namespace std;

class A {
	public:
	virtual ~A() { cout<<"destructor of A"<<endl; }
};

class B : public A {
	public:
	~B() { cout<<"destructor of B"<<endl; }
};

int main(){

	A *p = new B();
	delete p;

	return 0;
}

在此例中,A的析构函数用virtual来修饰,意味着所以派生于A的类及A都拥有虚析构函数,虚析构函数也是虚函数,所以会用到C++的动态绑定机制,这样当delete p的时候,编译器发现p虽然是A类型的,但是A拥有虚析构函数,所以它就按照虚函数的调用机制来安插代码从而在执行期调用p真正指向的对象的析构函数,所以最终可以在执行期找到B的析构函数,执行结果也如我们所料:先调用B的析构函数,再调用基类A的析构函数

destructor of B;

destructor of A;

时间: 2024-10-18 18:21:32

C++: delete与内存泄露的相关文章

Qt中内存泄露和退出崩溃的问题 delete

Qt中帮程序员做了一些内存回收的事情,但正因为这些反而让对此不熟悉的人会屡屡犯错. 收录一篇不错的文章: 在C++中学习过程中,我们都知道: delete 和 new 必须 配对使用(一 一对应):delete少了,则内存泄露,多了麻烦更大. Qt作为C++的库,显然是不会违背C++的前述原则的.可是: 在Qt中,我们很多时候都疯狂地用new,却很少用delete,缺少的 delete 去哪儿了?! 注:本文暂不涉及智能指针(smart pointer)相关的东西,你可以考虑 Qt 智能指针学习

BingMap频繁Add Pushpin和Delete Pushpin会导致内存泄露

最近在做性能测试的时候发现BingMap内存泄露(memory leak)的问题,查找了一些国外的帖子,发现也有类似的问题,但是没有好的解决办法. https://social.msdn.microsoft.com/Forums/en-US/3226f255-2ae1-4718-b848-5f24e76b64b0/your-pushpins-are-broken-addremove-leads-to-memory-leak?forum=bingmapsajax 经过一番尝试,找到了一个折中的解决

【C++】小项目——内存泄露检测器

在C++中,指针往往忘记释放.引起内存泄露. 1.内存泄露指: 内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏. 内存泄漏形象的比喻是"操作系统可提供给所有进程的存储空间正在被某个进程榨干",最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃.所以"内存泄漏"是从操作系统的角度

内存溢出和内存泄露的区别

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出. 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光. memory leak会最终会导致out of memory! 内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产

C/C++内存泄露检测

gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4Copyright (C) 2013 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 一.mtrace 1.介绍

Visual C++内存泄露检测—VLD工具使用说明 .

1.VLD工具概述 Visual Leak Detector(VLD)是一款用于Visual C++的免费的内存泄露检测工具.他的特点有:可以得到内存泄漏点的调用堆栈,如果可以的话,还可以得到其所在文件及行号: 可以得到泄露内存的完整数据: 可以设置内存泄露报告的级别:并且是开源免费的. 2.VLD下载 http://www.codeproject.com/tools/visualleakdetector.asp 本文后附有vld1.0的工具包,下载解包后就可使用. 3.VLD安装 方法一: 解

自己实现简易的内存泄露检测工具VLD

有一个很著名的内存泄露检测工具Visual leak detected想必大家都不陌生,但今天我们可以自己写一个简易版的.哈哈,自己动手,丰衣足食有木有!!! 它的原理就是我们重载了操作符new和delete,当用new开辟空间的时候,就讲这块空间串到我们定义的结构体MEMNode形成的链表中,(这是老师的写法,在main程序结束时,用check_vld()函数检测有没有内存泄露)但我觉得,如果我们动态开辟了一个对象,在它的析构函数里用delete释放的话,这种方法就不太可行.因为析构函数只有到

Java集群优化——必须了解的内存溢出与内存泄露

概念: 内存溢出 out of memory 是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出. 内存泄露 memory leak 是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光. 联系: memory leak会最终会导致out of memory,内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满

C++内存泄露的有效预防方法:谁使用,谁删除 (1.2)

内存泄露就是new出来的东西没有delete,我们能够这样:创建动态对象的人虽然使用new来创建对象:使用此对象的人负责释放此内存块. 比如:我和他人共享一个消息队列,他人将消息(new出来的对象)放到消息队列中,他不负责释放:我从消息队列里取消息,我一旦从消息队列里取出一个消息,消息队列里就不再有这个消息,消息的控制权和全部权都在我手上,我在用完之后就应该delete.这样就保证了代码编写的简单话,仅仅要大家都尊周这个简单的方法就能够保证没有内存泄露. 再比如:ACE中有个ACE_Messag