【问题标题】:Adding element to list crashes program...sometimes将元素添加到列表崩溃程序...有时
【发布时间】: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&amp; demo) 不是异常安全的。如果您选择使用rule of 0/3/5,您还需要始终牢记它们。
  • 我误解了你提到nullptr的部分。我撤回了我的第一条评论。但重点是问题可能出在提供的代码之外。考虑准备一个minimal reproducible example
  • @FrançoisAndrieux MainMenuState 类确实负责复制分配和构造。您指的是非异常安全的 std::bad_alloc 吗?
  • 我指的是堆栈展开不会(不能)自动delete 原始指针拥有的对象这一事实。构造函数的任何部分都不能抛出并不是很明显,这意味着您可能会泄漏,这甚至违反了基本的异常保证。也许构造函数不可能抛出,但这不能从 sn-p 中假设。即使不能,所显示的设计实践表明这种情况很可能广泛传播。如果您担心这个问题,使用智能指针可以避免这些问题以及许多其他问题。

标签: c++ list pointers crash


【解决方案1】:

这是您创建对象的顺序。

你调用Demo的构造函数列表中Demo的基类(Application)的构造函数和成员fsm的构造函数。在Demo 的构造过程中,首先构造基类,然后才构造Demo 的其他成员,它们被声明为-first fsm,并且仅在列表m_draw_list 之后。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 2018-08-31
    • 2013-04-27
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多