一道题目,这样有没有内存泄露?

ngbbxt 2013-01-29 03:46:33
在并没有虚析构函数的情况下,下面有内存泄露吗?


class ClxBase
{
public:
ClxBase():b(1009) {};
~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };
int b;
};
class ClxDerived : public ClxBase
{
public:
ClxDerived():a(2009) {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
int a;
};



ClxBase* clxBase = new ClxDerived();
delete clxBase;






...全文
2174 61 点赞 打赏 收藏 举报
写回复
61 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
笨蛋糕 2013-02-02
个人觉得new和delete是对应的,有建就有收。
  • 打赏
  • 举报
回复
sheepcorpse 2013-02-02
看了半天才知道楼主在纠结什么,其实new,delete最根本就是malloc 和 free对应的系统API嘛,只要地址对了,系统自然会找到对应的内存块清除。而且因为两类都是栈上分配的,所以两类的实例都是单纯的内存块,所以不会泄漏。 还有疑问的话,建议LZ去看下C++对像模型这本书,里面对类有比较基础的描述。
  • 打赏
  • 举报
回复
Bo_Lee 2013-02-02
总算是从顶楼下来了,总算是有点头绪了,其实你这个代码主要是没什么操作,在析构函数里面没做什么释放操作,假如你在类里面alloc了内存,那么就会出问题了!!
  • 打赏
  • 举报
回复
QQ515311445 2013-02-02
引用 3 楼 icechenbing 的回复:
不会泄露,你类中都没new操作。 确保每一个new,对应一个delete; 每一个malloc,对应一个free。
这位说得对,一点问题都没有,不会泄漏.
  • 打赏
  • 举报
回复
基类的析构必须加virtual 啊 不然,以后绝对会栽坑的。还查不出问题在哪。
  • 打赏
  • 举报
回复
会的吧。因为并没有构成多态啊。如果将基类的析构函数定义成析构函数才不会吧?
  • 打赏
  • 举报
回复
ngbbxt 2013-02-01
我已经知道答案了。 ClxBase* clxBase = new ClxDerived(); delete clxBase; 上面的代码,可以展开为: void* p = malloc(sizeof(ClxDerived)); ClxDerived* clxDerived = (ClxDerived*)p; clxDerived->ClxDerived(); ClxBase* clxBase = clxDerived; clxBase->~ClxBase(); free(clxBase); 因此,是否有内存泄露,主要看clxBase地址值是否等于p的地址值。 如果相等,则没有内存泄露; 如果不相等,则程序崩溃,也不存在内存泄露这一说法。
  • 打赏
  • 举报
回复
fkeujjpdc 2013-02-01
一看就是基类析构没加 virtual
  • 打赏
  • 举报
回复
MeAndJack 2013-02-01
引用 41 楼 zhao4zhong1 的回复:
引用 28 楼 smilenot 的回复:哪里来的泄漏?不泄漏的 把你的代码运行一万次,观察内存便知,最愚蠢莫过于这方法了 检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各……
这就是传说中的赵老师?笑而不语...
  • 打赏
  • 举报
回复
MeAndJack 2013-02-01
结论:楼主的这个例子肯定不存在内存泄露的! 之所以有这样的困扰是因为对指针的理解还不够透彻,当你定义指针的时候,需要指明它指向哪一种类型的对象,这样做,编译器就可以在寻址的时候进行指定类型大小字节的偏移了,例子中: ClxBase* clxBase = new ClxDerived(); 这个操作之后,根据C++对象模型,编译器这个时候会分配一块连续的内存空间,空间的大小就是ClxDerived的大小,完事之后,返回一个指针,也就是一个地址给指针变量clxBase,又因为指针变量类型定义为指向ClxBase的类型,没有关系,clxBase此时的值就是一个地址,指向的就是刚刚分配的一块连续的内存地址,记住:连续的地址,空间大小为ClxDerived大小! 但是这个时候如果我做自增操作的时候会是什么情况呢? clxBase++; 这个时候定义指针类型就起作用了,编译器这个时候对clxBase++进行偏移,而且偏移的大小就是ClxBase的大小,而不是ClxDerived的大小,但是clxBase指向的就是ClxDerived大小的连续空间,这个时候你终于能理解指针了吧。^_^ 而delete clxBase操作,实际上会调用C库的free函数,而对于free函数而言,它只接受一个参数,就是您让我要释放内存区的起始地址,它不管你是什么类型,然后就从该起始地址开始,释放该地址指向的连续空间,释放完了就完事了。最后,总该明白了吧。。。^_^ C++里面有很多的高级特性,内存管理是一个老大难的问题,新手一时会难以理解的,正常。。。建议多实践实践,多看看具有工业级代码的源码。。。
  • 打赏
  • 举报
回复
mplus 2013-02-01
只不过在楼主的最开始的例子中没有内存泄漏而已,不代表没有问题(如这样给其它类做基类就会有风险)。 后面很多都说得很明确了。
  • 打赏
  • 举报
回复
bljswpu 2013-01-31
没有 因为在类中你没有分配堆中的内存
  • 打赏
  • 举报
回复
风行踩火轮 2013-01-31
肯定不会内存泄露的,继承时的指针释放,你想想构造函数和析构函数的调用顺序就知道了,有问题好好想想,冷静,不要钻牛角尖
  • 打赏
  • 举报
回复
神-气 2013-01-31
new操作的时候编译器会在指针指向的内存前几个字节处放置这块内存的大小, delete 的时候参考这个
  • 打赏
  • 举报
回复
Star-light 2013-01-31
c++标准告诉我们这是undefined行为 5.3.5/4: If the static type of the operand [of the delete operator] is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behaviour is undefined. 具体内存释放、派生类析构函数是否执行和内存分配器,编译器,平台有关
  • 打赏
  • 举报
回复
quanben 2013-01-31
就这个例子原则上应该不会泄露。当然具体是设计delete的内部对内存分配释放的实现(对OS接口的调用)。这里的delete可以基本想象成大致在做free的操作,因为C++的类对象,即便是派生的所有内容都是在堆里一整块的,所以和传统的对内存分配无异,操作系统(内存管理)是保留有这个分配尺寸的信息的。没有问题。 但是如楼上所说的,析构函数(一般对潜在继承的基类总是)声明为virtual的好。但析构函数和这里上述说的整块内存释放没有任何关系。
  • 打赏
  • 举报
回复
漫步者、 2013-01-30
assert判断呗,就可以检测到
  • 打赏
  • 举报
回复
赵4老师 2013-01-30
引用 28 楼 smilenot 的回复:
哪里来的泄漏?不泄漏的 把你的代码运行一万次,观察内存便知,最愚蠢莫过于这方法了
检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
  • 打赏
  • 举报
回复
cfanandhacker2 2013-01-30
不过我实际测试了下,并没有泄露,书上说的是“可能泄露”,原来“可能”的意思是,析构函数没有声明为虚函数的话,在DELETE时不会调用派生类析构函数,如果派生类析构函数中有delete派生类中new出来的东西,这种情况下,由于派生类析构函数没有调用而没有delete才会泄露。 总结下来就是说,派生类析构函数中有delete的话才须把基类析构函数声明为虚函数。
  • 打赏
  • 举报
回复
hawke1234 2013-01-30
顶楼的代码不会泄露 7楼的代码会泄露,因为子类的构造函数中new了个pdata,而析构函数没有声明成虚函数。销毁对象时,子类的析构函数没有被调用,所以在子类内部new出来的pdata没有被释放掉。 new先是从堆上面申请内存块,第二部是调用类的构造方法来初始化刚申请的内存。 delete先调用类的析构方法来反初始化,再把刚申请的内存还给堆。
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
发帖
C++ 语言
加入

6.0w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
申请成为版主
帖子事件
创建了帖子
2013-01-29 03:46
社区公告
暂无公告