【问题标题】:Using delete on pointer to std::list?在指向 std::list 的指针上使用删除?
【发布时间】:2011-09-08 16:53:37
【问题描述】:

在我的程序中,我有一个指向 std::list 对象的指针,它是这样分配的。

d_list_p = new std::list<some_type*>();

然后在我的程序中我像这样删除它。

d_list_p->clear();
delete d_list_p;

由于某种原因,我在删除语句上触发了 Windows 断点。如果我在 delete 语句处中断,我会看到列表存在并且大小为 0。此外,我永远不会在引发错误的情况下将元素添加到列表中(我认为)。

代码正在使用 VS2005 的 MS VC++ 编译器进行编译。

错误消息显示 Windows 触发了指示内存损坏的断点。堆栈跟踪说明如下。

ntdll.dll!DbgBreakPoint()   
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
ntdll.dll!RtlpNtMakeTemporaryKey()  + 0x6735 bytes  
ntdll.dll!RtlpNtMakeTemporaryKey()  + 0x6b72 bytes  
ntdll.dll!RtlpNtMakeTemporaryKey()  + 0x7d5a bytes  
ntdll.dll!LdrAlternateResourcesEnabled()  + 0x33bd bytes    
ntdll.dll!RtlpUnWaitCriticalSection()  + 0x65b bytes    
msvcr80.dll!free()  + 0xcd bytes    
FM_Access_Library_NET.dll!std::list<FM_Access_Library::Logger_Callbacks *,std::allocator<FM_Access_Library::Logger_Callbacks *> >::`scalar deleting destructor'()  + 0x20 bytes C++

可能值得一提的是,这个删除语句是在 C++ 代码中构建到 .NET DLL 中的,因此程序是在混合模式下运行的。

【问题讨论】:

  • 您可能是(并且可能是)正在破坏内存的其他东西。
  • 嗯,你有内存损坏的地方。这里还不足以知道在哪里。

标签: c++ memory-management stdlist


【解决方案1】:

d_list_p 是一个类的成员吗?而且,该班级是否遵守Rule of Three

如果不是,那么d_list_p 的(副本)可能已被删除。

【讨论】:

  • d_list_p-&gt;clear(); 似乎已经执行了。大多数会在删除时停止的构建也会在 clear() 行上删除,如果它已经被删除的话。 (虽然,不能保证。你可能仍然是对的)
  • @Mooing,你可能是对的。我没有方便的 Windows,但如果他们使用 K&R 风格的 malloc,你肯定是对的,因为免费标头会侵占已释放的内存?
  • msdn.microsoft.com/en-us/library/bebs9zyz(v=VS.71).aspx debug builds 用 0xDD 替换空闲内存,用 0xFD 替换两边的无人区缓冲区。
  • 是的,你叫它。我在复制构造函数中复制了该列表指针,所以我有多个删除,因为删除发生在拥有该指针的类的析构函数中。
【解决方案2】:

您还需要迭代您的列表并删除其中的所有单个指针,因为如果您不这样做,就会泄漏它们。

你为什么要创建一个指向 std::list 的指针?只需使用std::list&lt;mytype&gt; mylist;

【讨论】:

  • 第一句中是否缺少“if”?
  • @Tomalak,毫无疑问。重新阅读 OP,告诉我您是否可以在其中找到问题。
  • +1 表示“为什么要创建指向 std::list 的指针?”几乎没有理由 new 标准容器。
  • @Rob:没有问题不是写一个不回答作为答案的借口。而是写评论。
  • @Rob:这很愚蠢。在很多情况下,您都希望容器比创建它的范围更长。
【解决方案3】:

当您调用delete 时,Windows 会仔细检查堆,因此delete 行是发现错误,而不是创建错误。错误在上面的行中。
大多数堆损坏是由 (A) 调用 delete 太多次 (B) 调用错误形式的 delete 或 (C) 访问堆分配的数组超出范围引起的。我们可以看到 A 和 B 不是问题,所以可能是 C。查找数组访问,并围绕它们断言以验证范围。

【讨论】:

  • -1,堆?什么是堆? C++ 标准中没有提到堆。
  • Windows 是否进行根检查(或任何正确的术语)以查看您是否正在删除当前在别处引用的内存?至少在您运行调试器时。因为看起来这就是它发现错误的方式。
  • @Als:标准中没有提到堆很好,因为我从来没有提到标准,问题不是标准问题。我的回答是对观察到的行为的解释,以及如何解决问题的建议。
  • @Mooing:如果不正确,怎么办(为什么?我的第一条评论已经解决了这个问题)?
  • @Ian:windows 不做“root”检查。在调试版本中,MSVC 会将魔术常量放入越界区域,并将不同的魔术常量放入已删除的内存中。您不小心更改了这些值,因此 Windows 会告诉您您写入的内容超出了数组的末尾。在发布版本中,它可能会简单地崩溃或做完全随机的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多