这是一个安全的代码吗

Is this a safe code?

本文关键字:安全 代码 一个      更新时间:2023-10-16

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

顺便说一下,我已经在GNULinux(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;
}

我不确定你想做什么,但是。。。

线路:

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

导致未定义的行为。首先显式地破坏对象,然后调用delete,它调用实际上已成为原始内存的内容。delete this;应该足够了。您唯一想显式调用的时间析构函数是在分离分配和初始化时,在这种情况下,您将使用placementnew来构建对象。