【发布时间】:2017-11-08 16:27:31
【问题描述】:
我正在开发一个 GUI 项目,由于某种原因,以下调用 add_gfx_object() 使我的程序崩溃。
MainMenuState::MainMenuState(Demo& demo)
: m_start_button{new Button(Sol::Rectangle{Sol::Vector{10, 10}, 100, 30},
[] {std::cout << "clicked";})}
{
demo.add_gfx_object(m_start_button); // <-- crashes program
}
这里列出了Demo类中的相关代码。
class Demo : public Sol::Application
{
public:
StateMachine<Demo> fsm;
Demo();
~Demo();
//...
void add_gfx_object(const GraphicalEntity* const obj) {m_draw_list.push_back(obj);}
private:
std::list<const GraphicalEntity*> m_draw_list;
void draw_objects();
};
奇怪的是,这个对 add_gfx_object() 的调用并没有使我的程序崩溃。
Demo::Demo()
: Application("Demo", 800, 600, false), fsm(*this, new MainMenuState(*this))
{
add_gfx_object(new Button(Sol::Rectangle(), []{})); // <-- does not crash program
}
在这些示例中将 Button 指针替换为 nullptr 会产生相同的结果。尽管我想提供有关该问题的更多信息,但我无法提供。谁能解释一下为什么我的程序总是崩溃?
【问题讨论】:
-
@FrançoisAndrieux 怎么样?用 nullptr 替换 Button 指针会在两种情况下产生相同的结果。
-
当心原始拥有指针。例如,使用原始拥有指针导致
MainMenuState::MainMenuState(Demo& demo)不是异常安全的。如果您选择使用rule of 0/3/5,您还需要始终牢记它们。 -
我误解了你提到
nullptr的部分。我撤回了我的第一条评论。但重点是问题可能出在提供的代码之外。考虑准备一个minimal reproducible example。 -
@FrançoisAndrieux MainMenuState 类确实负责复制分配和构造。您指的是非异常安全的 std::bad_alloc 吗?
-
我指的是堆栈展开不会(不能)自动
delete原始指针拥有的对象这一事实。构造函数的任何部分都不能抛出并不是很明显,这意味着您可能会泄漏,这甚至违反了基本的异常保证。也许构造函数不可能抛出,但这不能从 sn-p 中假设。即使不能,所显示的设计实践表明这种情况很可能广泛传播。如果您担心这个问题,使用智能指针可以避免这些问题以及许多其他问题。