将元素添加到列表会使程序崩溃..有时

Adding element to list crashes program...sometimes

本文关键字:程序 崩溃 有时 列表 元素 添加      更新时间:2023-10-16

我正在处理一个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
}

在这些示例中,用nullptr替换Button指针会产生相同的结果。尽管我很想提供更多关于这个问题的信息,但我无法提供。有人能深入了解我的程序不断崩溃的原因吗?

这是中创建对象的顺序。

调用Demo的构造函数列表中Demo的基类(Application)的构造函数和成员fsm的构造函数。在构造Demo的过程中,首先构造基类,然后才按照声明的顺序构造Demo的其他成员——首先是fsm,然后是列表m_draw_list

但是,对于fsm的构造函数,您试图将调用MainMenuState的构造函数的指针结果传递给最后一个*this,它是一个尚未列出的部分构造的Demo对象。因此,在这个对MainMenuState(Demo& demo)的调用中,程序崩溃的原因是意图使用未初始化的列表。

您必须考虑如何组织代码并防止对象创建的循环依赖性。您可能需要将一些参数传递给已经完全创建的对象,例如,在构造函数的主体中,所有成员都已经构造好了,包括列表,就像在"工作"的示例中一样。在这种情况下,您也可以在公共fsm之前声明私有列表m_draw_list