我的代码在删除时崩溃了

时间:2011-09-16 19:00:11

标签: c++ segmentation-fault destructor delete-operator self-destruction

尝试删除时会出现分段错误。

我知道你对删除它的想法,但我的前任遗留下来了。我知道some precautions I should take,已经过验证和处理。

我没有得到什么样的条件可能导致这次崩溃,只是偶尔发生一次。大约95%的时间代码运行完美,但有时这似乎在某种程度上被破坏并崩溃。

该类的析构函数没有做任何事情。

我是否应该假设某些东西在其他地方破坏了我的堆并且这个指针以某种方式搞砸了?

编辑:根据要求,崩溃的代码:

long CImageBuffer::Release()
{
  long nRefCount = InterlockedDecrement(&m_nRefCount);
  if(nRefCount == 0)
  {
    delete this;
  }
  return nRefCount;
}

该对象是使用new创建的,它不是任何类型的数组。

3 个答案:

答案 0 :(得分:1)

最明显的答案是:不要删除它。

如果你坚持这样做,那么使用常见的方法来发现错误:
1.使用valgrind(或类似工具)查找内存访问问题 2.写单元测试
3.使用调试器(准备loooong盯着屏幕 - 取决于你的项目有多大)

答案 1 :(得分:1)

您好像newdelete不匹配。请注意delete this;只能用于使用new分配的对象(如果被覆盖operator new,或者C ++运行时的多个副本,则new匹配当前范围内的delete

答案 2 :(得分:0)

重新分配时崩溃可能是一种痛苦:它不应该发生,当它发生时,代码太复杂而不能轻易找到解决方案。

注意:使用InterlockedDecrement假设您正在使用Windows。

记录所有内容

我自己的解决方案是大量记录构造/破坏,因为在调试时崩溃可能永远不会发生:

  1. 记录构造,包括this指针值和其他相关数据
  2. 记录销毁,包括this指针值和其他相关数据
  3. 通过这种方式,您将能够查看this是否已被解除分配两次,甚至根本没有分配。

    ......一切,包括堆栈

    我的问题发生在Managed C ++ / .NET代码中,这意味着我可以轻松访问堆栈,这是一种祝福。你似乎在普通的C ++上工作,所以检索堆栈可能是件苦差事,但它仍然非常有用。

    您应该尝试从Internet加载代码以打印每个日志的当前堆栈。我记得为此而玩http://www.codeproject.com/KB/threads/StackWalker.aspx

    请注意,您需要在调试版本中,或者在可执行文件中包含PDB文件,以确保完整打印堆栈。

    ......一切,包括多次崩溃

    我相信你在Windows上:你可以尝试捕获SEH异常。这样,如果发生多次崩溃,您将全部看到它们,而不是只看到第一次崩溃,并且每次您都能在日志中标记“OK”或“CRASHED”。我甚至使用地图来记住分配/解除分配的地址,从而组织日志以将它们一起显示(而不是按顺序)。

    我在家,所以我无法向您提供确切的代码,但在这里,Google是您的朋友,但要记住的是您不能拥有__try / {{ 1}} handdler无处不在(C ++ unwinding和C ++异常处理程序与SEH不兼容),因此你必须编写一个中间函数来捕获SEH异常。

    你的崩溃线程是否相关?

    最后但并非最不重要的是,“我只发生了5%的时间”症状可能是由于不同的代码路径执行造成的,或者您有多个线程与同一数据一起播放的事实。

    InterlockedDecrement部分困扰我:你的对象是否生活在多个线程中?并且m_nRefCount是否正确对齐并__except volatile

    正确对齐的LONG部分很重要,在这里。

    如果您的变量不是LONG(例如,它可能是LONG,而不是64位Windows上的size_t,那么该函数可能很好以错误的方式工作。

    对于未在32字节边界上对齐的变量,也可以这样说。您的代码中是否有LONG条说明?您的projet文件是否更改了默认对齐方式(我假设您正在使用Visual Studio)?

    对于#pragma pack()部分,volatile似乎会产生读/写内存屏障,因此InterlockedDecrement部分不应是强制性的(请参阅http://msdn.microsoft.com/en-us/library/f20w0x5e.aspx)。