这是一个安全的代码吗?

时间:2014-10-02 18:01:11

标签: c++ virtual destructor

  

我的问题是您认为下面显示的代码是否安全?这样的代码可以生成运行时故障,例如:__PureVirtualCalled() at 0x9000000007ef90c?

     

顺便说一下,我在GNU Linux(64位)上使用g ++ 4.3.2编译了这段代码。输出是:

~derived called.
~base() called.
~base() called.
foo() called.
     

请注意,下面给出的代码只是我编写的一个小程序来解释问题。真正的类实际上是一个引用计数器的实现,只有当它的计数降到零时才会自行处理。手动调用析构函数的原因是为了避免虚函数调用的开销(引用计数器类派生自抽象计数器类)。可以通过显式指定要调用的函数来抑制虚拟调用,尤其是在类是派生最多的函数时。但是,这显然不适用于虚拟析构函数。

     

另外一个信息,得到上述错误的真正应用程序是一个多线程应用程序。

     

请注意,我试图解释为什么运行时会引发上述错误。它间歇性地这样做。

     

代码

#include <iostream>

class base {
public:
    virtual ~base() {
        std::cout << "~base() called." << std::endl;
    }

    virtual void dispose() = 0;

    void foo() {
        dispose();
        std::cout << "foo() called." << std::endl;
    }
};

class derived : public base {
public:
    ~derived() {
        std::cout << "~derived called." << std::endl;
    }

    void dispose() {
        // Intention here is to suppress the virtual function call. 
        this->derived::~derived();
        delete this;
    }
};

int main() {
    base* ptr = new derived;
    ptr->foo();
    return 0;
}

1 个答案:

答案 0 :(得分:4)

我不确定你要做什么,但是......

行:

this->derived::~derived();
delete this;

导致未定义的行为。首先你明确地破坏了 对象,然后你调用delete,它调用析构函数 什么有效地成为原始记忆。 delete this; 应该够了。您唯一要明确调用的时间 析构函数是在分配和初始化时, 在这种情况下,您将使用placement new来构建 物体。

相关问题