gpt4 book ai didi

c++ - 基类中的非虚析构函数,但派生类中的虚析构函数导致段错误

转载 作者:可可西里 更新时间:2023-11-01 18:28:19 24 4
gpt4 key购买 nike

最近在一次工作面试中,我被问及当基类的析构函数未声明为虚拟时派生类中内存泄漏的问题。

我写了一个小测试来确认我的答案,但我发现了一些有趣的东西。显然,如果您通过 new 创建一个 Derived 对象,但将其指针存储为 Base*,则不会调用派生对象的析构函数,如果指针被删除(我对问题的回答就这么多)。

我认为在这种情况下派生类的析构函数是否为虚函数无关紧要,但在我的系统上,以下代码显示了其他情况:

#include <iostream>
#include <string>

// just a helper class, printing its name out when it is destructed
class PrintOnDestruct
{
public:
PrintOnDestruct( const std::string& name )
: name_( name )
{}

~PrintOnDestruct()
{
std::cout << "Destructing: " << name_ << std::endl;
}

protected:

std::string name_;
};

// the Base class
class Base
{
public:
Base()
{
print_on_destruct_ = new PrintOnDestruct( "Base" );
}

// the destructor is NOT virtual!
~Base()
{
delete print_on_destruct_;
}

protected:

PrintOnDestruct* print_on_destruct_;

};

// the NonVirtualDerived class, doesn't have a virtual destructor either
class NonVirtualDerived : public Base
{
public:
NonVirtualDerived()
: Base()
{
print_on_destruct_child_ = new PrintOnDestruct( "NonVirtualDerived" );
}

// the destructor is NOT virtual!
~NonVirtualDerived()
{
delete print_on_destruct_child_;
}

protected:

PrintOnDestruct* print_on_destruct_child_;

};

// the VirtualDerived class does have a virtual destructor
class VirtualDerived : public Base
{
public:
VirtualDerived()
: Base()
{
print_on_destruct_child_ = new PrintOnDestruct( "VirtualDerived" );
}

// the destructor is virtual!
virtual ~VirtualDerived()
{
delete print_on_destruct_child_;
}

protected:

PrintOnDestruct* print_on_destruct_child_;

};

int main()
{
// create the two child classes
Base* non_virtual_derived = new NonVirtualDerived;
Base* virtual_derived = new VirtualDerived;

// delete the two objects
delete non_virtual_derived; // works as expected (only calls Base's destructor, the memory of NonVirtualDerived will be leaked)
delete virtual_derived; // segfault, after calling Base's destructor

return 0;
}

我本以为程序会输出下面两行然后正常退出:

Destructing: Base
Destructing: Base

我得到了那个输出,但在第二行之后程序立即退出并出现段错误。以及消息:

*** Error in `...': free(): invalid pointer: 0x00000000006020e8 ***

我已经更改了对 delete 的两次调用的顺序,但是程序总是会在对 delete virtual_derived; 的调用中出现段错误。谁能告诉我为什么会这样?

最佳答案

答案就在声明中:

    Base* virtual_derived = new VirtualDerived;

您正在尝试“释放”一个不是由“malloc”返回的地址。要了解原因,请将这一行替换为

    VirtualDerived* x = new VirtualDerived;
Base* virtual_derived = x;

如果打印这两个地址,您会注意到“x”和“virtual_derived”具有不同的值。 “malloc”返回的地址(通过“new”)是“x”,传递给“free”(通过“delete”)的地址是“virtual_derived”。

关于c++ - 基类中的非虚析构函数,但派生类中的虚析构函数导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19542202/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com