最后我找到了一个非常奇怪的错误,这是由双重调用析构函数引起的。这是重现该错误的最小代码:
#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% 的时间)会破坏我的真实代码中的事件系统容器,从而导致段错误,但很少它不会破坏它并且一切正常。