BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #101842同步于 2022/4/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

【问题】关于非虚析构函数是否存在内存泄漏的问题

brz222
2022/4/25镜像同步19 回复
面试的时候被问到一道题:一个基类和一个子类,基类的析构函数非虚,子类有一个int b成员,main()里面new一个子类对象,用基类指针指向它,delete基类指针会造成子类的成员b内存泄漏吗? 当时我想的是非虚的析构函数不会析构子类成员,所以b会造成内存泄漏,但是面试官说b不是动态申请的内存,会在main()函数之后被析构掉,所以不会造成内存泄漏,这种说法貌似是没问题的,实测了一下编译器没有抛出异常,但是如果把int b换成一个成员对象Data,基类的析构函数仍然非虚,实测发现子类和Data的析构函数都没有输出(打断点发现没有执行析构函数),如下图,但是也没有抛出异常,没有析构Data但也没有内存泄漏,想问下大佬这是咋回事啊?测试平台VS2019_v142,C++17,x86
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
brz222机器人#1 · 2022/4/25
【 在 brz222 的大作中提到: 】 : 面试的时候被问到一道题:一个基类和一个子类,基类的析构函数非虚,子类有一个int b成员,main()里面new一个子类对象,用基类指针指向它,delete基类指针会造成子类的成员b内存泄漏吗? : 当时我想的是非虚的析构函数不会析构子类成员,所以b会造成内存泄漏,但是面试官说b不是动态申请的内存,会在main()函数之后被析构掉,所以不会造成内存泄漏,这种说法貌似是没问题的,实测了一下编译器没有抛出异常,但是如果把int b换成一个成员对象Data,基类的析构函数仍然非虚,实测发现子类和Data的析构函数都没有输出(打断点发现没有执行析构函数),如下图,但是也没有抛出异常,没有析构Data但也没有内存泄漏,想问下大佬这是咋回事啊?测试平台VS2019_v142,C++17,x86 : [upload=1][/upload]
shuidi机器人#2 · 2022/4/25
delete会把整个对象释放掉。基类指针指向子类对象,delete基类指针会把整个对象都释放掉。 即使没有调用子类的delete,但是也把子类空间释放了。 若子类额外申请了内存,那么这片内存不会被释放,因为没有调用子类的析构函数。
shuidi机器人#3 · 2022/4/25
面试官说的应该有问题。delete基类指针会直接把整个对象释放掉,而不是在main函数之后再释放。
shuidi机器人#4 · 2022/4/25
delete如何确定要释放多少字节呢?这个在编译时期就确定了,这个释放的长度信息在头部中保存。 个人理解是这样的
zsj1227机器人#5 · 2022/4/25
这个应该不是编译期确定的吧,之前看侯捷的视频,new的时候才会将内存的大小存起来 【 在 shuidi 的大作中提到: 】 : delete如何确定要释放多少字节呢?这个在编译时期就确定了,这个释放的长度信息在头部中保存。 : 个人理解是这样的
a912655391机器人#6 · 2022/4/25
个人觉得面试官说的应该没有问题. 1.new derive的时候会按照derive类的大小来申请动态内存,delete的时候会根据申请的大小(这个数值应该会存在分配空间的头部)来进行释放,若子类中只有一个data类型,这个数据并不是动态分配的,则delete p的时候,整块内存都会回收,不存在内存泄露. 2.至于没有调用derive的析构函数,是因为delete p,p是指向base类型的,然而base类型并没有虚析构函数,则编译器应该会直接调用base的析构函数,跳过derive的.但是由于derive里面的数据成员是data,其实也没有什么影响,若derive里面的是成员是data*,指向动态分配的内存,按照图中写的析构方式则会造成内存泄露,泄露的是data*指向的那一部分内存. 3.另外内存泄露是不会抛出异常的,只会导致当前进程的可用内存空间变小.引用非法的内存地址(解引用一个已经释放的内存地址)才会触发异常.检测内存泄露有一些好用的工具,比如valgrind
brz222机器人#7 · 2022/4/25
【 在 shuidi 的大作中提到: 】 : delete会把整个对象释放掉。基类指针指向子类对象,delete基类指针会把整个对象都释放掉。 : 即使没有调用子类的delete,但是也把子类空间释放了。 : 若子类额外申请了内存,那么这片内存不会被释放,因为没有调用子类的析构函数。 受教了,非常感谢。
brz222机器人#8 · 2022/4/25
受教了,非常感谢 【 在 a912655391 的大作中提到: 】 : 个人觉得面试官说的应该没有问题. : 1.new derive的时候会按照derive类的大小来申请动态内存,delete的时候会根据申请的大小(这个数值应该会存在分配空间的头部)来进行释放,若子类中只有一个data类型,这个数据并不是动态分配的,则delete p的时候,整块内存都会回收,不存在内存泄露. : 2.至于没有调用derive的析构函数,是因为delete p,p是指向base类型的,然而base类型并没有虚析构函数,则编译器应该会直接调用base的析构函数,跳过derive的.但是由于derive里面的数据成员是data,其实也没有什么影响,若derive里面的是成员是data*,指向动态分配的内存,按照图中写的析构方式则会造成内存泄露,泄露的是data*指向的那一部分内存. : ...................
baymaxhwy机器人#9 · 2022/4/25
class里面的malloc/new才需要调用析构去free/delete,如果没有就不需要,new的时候会给你分配class成员变量大概这么大小的内存,如果有一些变量是pointer,那么需要为这些pointer进行alloc和free的就是class本身的逻辑,main里面delete也只会回收当时给你分配的那些内存,class里面的pointer分配的需要class的析构去回收(这个时候才需要虚析构)