【问题标题】:Strange double destructor call when using shared_ptr使用 shared_ptr 时奇怪的双重析构函数调用
【发布时间】:2013-01-22 08:11:49
【问题描述】:

最后我找到了一个非常奇怪的错误,它是由双重调用析构函数引起的。这是重现该错误的最小代码:

#include <iostream>
#include <memory>
#include <set>

class cEventSystem {
    public:
        cEventSystem() {
            std::cout << "constructor: " << this << std::endl;
        }
        ~cEventSystem() {
            std::cout << "destructor: " << this << std::endl;
        }
};

class cSubscriber {
    public:
        cSubscriber(cEventSystem& eventSystem) : eventSystem(eventSystem) {}
        virtual ~cSubscriber() {}
        virtual void onEvent() = 0;
    protected:
        cEventSystem& eventSystem;
};

class cTileBrowser: public cSubscriber {
    public:
        cTileBrowser(cEventSystem eventSystem) : cSubscriber(eventSystem) {}
        void onEvent() {}
};

class cGui: public cSubscriber {
    public:
        cGui(cEventSystem& eventSystem) : cSubscriber(eventSystem) {
            tileBrowser = std::make_shared<cTileBrowser>(eventSystem);
        }
        void onEvent() {}
        std::shared_ptr<cTileBrowser> tileBrowser;
};

int main() {
    cEventSystem eventSystem;
    cGui gui(eventSystem);
}

输出是:

 constructor: 0x7fffffffe67f
 destructor: 0x7fffffffe2df
 destructor: 0x7fffffffe67f

如您所见,第一个析构函数是不需要的,它在根本没有构造的不同对象上调用(地址不同),但在我的真实代码中,地址足够接近,它破坏了我拥有的容器在事件系统中。

调试表明是 make_shared 导致了析构函数调用。

是什么导致了不需要的析构函数调用,我该如何摆脱它? 我使用带有 c++11 标志的 g++4.7。

问题在于,不需要的析构函数调用通常(90% 的时间)会破坏我的真实代码中的事件系统容器,从而导致段错误,但很少它不会破坏它并且一切正常。

【问题讨论】:

    标签: c++ c++11 g++ destructor shared-ptr


    【解决方案1】:

    CTileBrowser 构造函数按值获取其参数。您可能会看到为该构造函数创建的临时副本被破坏。将其更改为参考参数,我敢打赌问题会消失。

    【讨论】:

    • 伙计,你是英雄,它现在可以在我的真实代码中使用!但是为什么临时副本如此不安全,以至于它会破坏我在内存中的数据呢?我几乎总是通过引用传递(这是一个错误),但至少对我来说似乎很奇怪。
    • @user1873947,由于复制构造函数是编译器生成的,它可能做错了事。例如,如果它复制了一个指针,然后析构函数将其删除,则在原始对象中留下一个悬空指针。
    • @Mark Ransom 就是这样。在我的真实代码中,我有一组指针。
    • 谢谢大家,问题解决了。如果可能,我会接受。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 2019-05-04
    • 1970-01-01
    • 2012-04-04
    • 2017-05-24
    • 1970-01-01
    相关资源
    最近更新 更多