【问题标题】:Deleting an object created with "new"删除使用“new”创建的对象
【发布时间】:2014-03-30 21:15:30
【问题描述】:

我的类 Note 中的对象通过将指针保存在名为 m_noteList 的列表中来存储:

QList< QSharedPointer<Note> > m_noteList;   

我正在通过以下方式创建该类的对象:

QSharedPointer<Note> note(new Note(this));
m_noteList << note;

删除(在获得正确的索引idx 以识别对象之后):

delete m_noteList[idx].data();

QtCreator 中的错误消息(调试模式)

HEAP[MyApp.exe]: 
HEAP: Free Heap block 024FC240 modified at 02500330 after it was freed

还有拆解器:

0x777349ab  <+0x0000>         cmpb   $0x0,0x2(%eax)
0x777349af  <+0x0000>         je     0x777349c6
0x777349b1  <+0x0000>         movb   $0x1,0x7774d640
0x777349b8  <+0x0000>         mov    %ecx,0x7774d644
0x777349be  <+0x0000>         int3
0x777349bf  <+0x0000>         movb   $0x0,0x7774d640   //<-- Here is a stop mark
0x777349c6  <+0x0000>         ret
0x777349c7  <+0x0000>         nop
...

我也试过这个:

m_noteList.removeAt(idx);

这也不起作用。操作系统发出的SIGSEGV 信号停止了进程(分段错误)

所以我真的不知道我做错了什么以及如何解决它

我的解决方案很脏:为我的对象设置某种deleted-tag,但我需要在所有其他函数中检查它以忽略该对象...

编辑:

我意识到一件事:如果我删除一个注释(使用removeAt()),它会被删除(我通过查看控制台打印输出看到它),但它的 gui 并没有消失。然后,如果我再次单击该对象的删除注释的特定按钮,应用程序将崩溃(因为它不再真正存在,而只有 gui)。但是如果我之前写过这个deleteLater,在删除它之后,gui 也会消失,一切看起来都很好。 谁能解释一下,为什么?

m_noteList.at(idx)->deleteLater();
m_noteList.removeAt(idx);

【问题讨论】:

  • 你不应该deleteQSharedPointer管理的资源。
  • 那么我应该如何删除它,或者我可以创建一个没有QSharedPointerQList&lt;Note&gt;?不确定我是否真的需要它。
  • 一旦没有共享指针处理相同的资源,删除就会自动发生。这就是共享指针的意义(不是双关语)。
  • 然后,只要共享指针超出范围,它就会被删除。但是共享指针用于共享所有权。如果您没有共享所有权,则不需要共享指针。
  • @juanchopanza 这并不完全正确,因为您不能真正将QScopedPointerstd::unique_ptr 放入Qt 容器或实际上任何容器中。只有支持emplace_back 的 C++11 容器才支持此功能。对于在容器中存储指针,QSharedPointer 是唯一的解决方案。

标签: c++ qt pointers segmentation-fault


【解决方案1】:

您混淆了三种内存管理策略:

  1. QObject父子内存管理:当一个父QObject被删除时,它会自动删除所有子QObjects。解释here。删除对象是自动完成的,因此不需要显式删除。

  2. QSharedPointer内存管理:当最后一个引用对象的QSharedPointer被删除时,该对象被删除。解释here。该对象会自动删除,因此不需要显式删除。

  3. “手动”内存管理:new 一个对象和delete 一个对象在正确的时间。在 C++ 标准中解释。必须手动删除该对象。

您应该只选择以上其中一项,以确保您不会重复删除对象。我建议根据您计划如何使用这些对象在 #1 和 #2 之间进行选择。如果您打算在“父母”之间共享对象,请使用 #2,否则使用 #1。

【讨论】:

    【解决方案2】:

    给定一个QList&lt;QSharedPointer&lt;Note&gt;&gt; m_noteList

    Note 对象的删除由m_noteList.removeAt(idx) 完成,假设没有其他现存的指针副本。您只需破坏指向给定注释的最后一个共享指针,就是这样。对共享指针的数据调用 delete总是错误

    我无法用 removeAt 重现您的问题 - 只有当您先 delete 注释时才会发生这种情况,您不应该这样做。

    【讨论】:

    • 好吧,我认为,从技术上讲,两次删除指针被认为是未定义的行为
    • @Jefffrey 或者,用简单的语言来说,一个错误:) 人们经常感到困惑,因为他们没有认识到未定义行为和实现定义行为之间最重要的区别。错误很简洁明了:)
    • 标准没有说明这种情况下的错误。根据标准,对于未定义的行为,任何事情都可能发生。即使你被独角兽杀死。所以,是的,不要做未定义的行为。 :)
    • @Jefffrey 提交错误具有简单的英语含义,与编程语言标准无关。编写具有未定义行为的 C++ 代码是错误的。就这么简单。错误并不意味着诊断或类似的事情。这是错误的人类行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多