从矢量中删除元素后出现隔离错误
Segfault after deleting elements from vector
我目前正在做一个项目,更准确地说是一个七巧板游戏。 我有一个段错误的问题,我不明白为什么。
鉴于我有一个完整的项目,我将尝试简化问题: 我有一个GameManager类,它特别包含一个Menu对象(和其他东西,但我认为这并不重要。游戏管理器用于初始化此对象并对其进行管理。 菜单包含一个 Button 向量(每个按钮都有一个 lambda,用于在用户单击它时执行操作(。
std::vector<std::unique_ptr<Button>> buttons;
为了说明它是如何工作的,我将举一个例子:如果用户单击"加载"按钮,游戏管理器将删除菜单中的当前按钮,并在该菜单中添加新按钮。
void GameManager::initMainMenuButtons() {
...
menu -> addButton(std::unique_ptr<Button>(new Button(x1, y1, x2, y2, "Create",
[this]{
std::cout << "Create level" << std::endl;
menu->clear()
initCreateLevelButtons();
actionManager->setMenu(menu);
}
)));
...
}
在该代码示例中,我有一个方法 initMainMenuButtons,它在菜单中添加了几个按钮,例如"加载"或"退出"。 当用户单击"创建"时,我想更改界面(添加和删除按钮(。因此,要删除按钮,我调用方法clear((
void Menu::clear() {
buttons.clear();
decorationPieces.clear(); // not interesting
}
我正在使用unique_ptr,因此,我不必删除按钮。 到目前为止,没问题:按钮的向量似乎是空的(大小为 0(。 接下来,调用方法 initCreateLevelButtons((。此方法与 initMainMenu 非常相似 :它在菜单中添加按钮,没有别的。在此调用期间,按钮似乎已正确添加到矢量中,我在最后打印了矢量的内容,并且矢量包含正确的按钮。
在那里,问题出现了:调用 initCreateLevelButtons(( 后,当我想使用菜单时会出现段错误,因此,actionManager->setMenu(menu);
不起作用。我尝试打印菜单std::cout << menu << std::endl
,并测试此指针是否为 nullptr,但它也不起作用。我不明白为什么菜单在 initCreateLevelButtons(( 的最后一行似乎是正确的,并且紧接着变得无效。 如果我不清除按钮的向量(菜单>清除指令(,程序就可以工作,但是,最后一个按钮仍然在这里(。
我尝试使用原始指针,我注意到只要不删除按钮,程序就可以清除向量(如果我添加一个循环来删除按钮,问题就出现了(,所以,我认为问题是按钮删除。我不知道为什么,我被困住了。 我不知道我是否解释了它,因为,正如我已经说过的,代码是整个项目的一部分,如果不引入其他东西,很难引入类。 如果你想要细节或完整的方法代码,我可以提供它们。
menu
维持某些button
的生命周期button
维持lambda
的使用寿命- 单击"
button
lambda
"时会清除menu
menu
析构函数清除button
,button
清除lambda
lambda
在实际上已经被销毁时继续执行 ->未定义的行为以崩溃结束
现在的问题是:你拥有Button
课程吗?
如果是,那么修复它的最简单方法是在按钮中调用 lambda 的副本。
当你调用menu->clear()
时,它会调用buttons.clear()
。
当你调用buttons.clear()
时,它会破坏buttons
的所有元素。
当您销毁"创建"按钮的unique_ptr
时,它会破坏"创建"按钮。
我假设button
的回调是一个std::function
。当button
被摧毁时,std::function
也被摧毁。
销毁std::function
时,回调 lambda 对象 ([this]{...}
( 将被销毁。
lambda 中的this
指针存储在 lambda 对象中。因此,现在保存this
指针的内存已被解除分配。
由于actionManager
是GameManager
的成员变量,actionManager->setMenu(menu)
确实this->actionManager->setMenu(menu)
崩溃,因为它使用了悬空指针。
一种解决方法是将按钮代码放在GameManager
函数中(因为GameManager
不会被破坏(,并从 lambda 调用它。然后,如果您在该功能中销毁按钮也没关系。销毁其代码当前正在运行的对象是可以的,只要您小心不要在销毁该对象后访问该对象即可!这对于 std::function 也是可以的。即:
[this]{
// move the rest of the code to the CreateLevel function
this->CreateLevel();
// At this point the lambda has been destroyed, but it's not a problem
// because we don't do anything.
}
- 从矢量中删除元素后出现隔离错误
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- 线程时访问静态映射时出现隔离错误
- 并行快速排序分区中的隔离错误
- C++多线程程序:变量定义为类成员的隔离错误
- TFLite 隔离错误,通过获取C++输入和输出
- 我只是在寻找模板,在我的书中找到了这段代码,这显示了隔离错误?
- pthread_create中错误 4 的隔离错误
- 递归树遍历/分支删除的隔离错误
- 在类模板上使用 arm gcc 编译期间的隔离错误
- 从大量文件读取时出现隔离错误
- 在PHP扩展中使用emalloc从线程时出现隔离错误
- 通过 Boost Python 在C++对象之间传递共享指针的隔离错误
- 在QT中单击菜单时出现隔离错误
- 尝试访问标头声明成员时出现隔离错误
- 搜索链表时出现隔离错误
- 模板化子类析构函数中的隔离错误
- 插件中节点.js/Nan 回调C++不频繁的隔离错误
- 将行添加到 GTKTreeView 时的隔离错误
- 找不到命令时打开的隔离错误