我的代码在删除此代码时崩溃

发布于 2024-12-04 18:04:37 字数 571 浏览 1 评论 0原文

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

我知道你想删除这个,但它是我的前任留下的。我知道我应该采取的一些预防措施 ,这些都已经过验证并得到处理。

我不知道什么样的情况可能会导致这次崩溃,只是偶尔发生一次。大约 95% 的情况下,代码运行得很好,但有时似乎会以某种方式损坏并崩溃。

顺便说一句,该类的析构函数不执行任何操作。

我是否应该假设有什么东西正在其他地方破坏我的堆并且 this 指针以某种方式搞砸了?

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

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

该对象已使用新创建,它不在任何类型的数组中。

I get a segmentation fault when attempting to delete this.

I know what you think about delete this, but it has been left over by my predecessor. I am aware of some precautions I should take, which have been validated and taken care of.

I don't get what kind of conditions might lead to this crash, only once in a while. About 95% of the time the code runs perfectly fine but sometimes this seems to be corrupted somehow and crash.

The destructor of the class doesn't do anything btw.

Should I assume that something is corrupting my heap somewhere else and that the this pointer is messed up somehow?

Edit : As requested, the crashing code:

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

The object has been created with a new, it is not in any kind of array.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暮色兮凉城 2024-12-11 18:04:37

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

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

The most obvious answer is : don't delete this.

If you insists on doing that, then use common ways of finding bugs :
1. use valgrind (or similar tool) to find memory access problems
2. write unit tests
3. use debugger (prepare for loooong staring at the screen - depends on how big your project is)

那支青花 2024-12-11 18:04:37

看来您的 newdelete 不匹配。请注意,delete this; 只能用于使用 new 分配的对象(并且在覆盖 operator new 的情况下,或多个副本C++ 运行时的特定 new 与当前作用域中找到的 delete 相匹配)

It seems like you've mismatched new and delete. Note that delete this; can only be used on an object which was allocated using new (and in case of overridden operator new, or multiple copies of the C++ runtime, the particular new that matches delete found in the current scope)

行至春深 2024-12-11 18:04:37

释放时的崩溃可能会很痛苦:这种情况不应该发生,而当它发生时,代码太复杂而无法轻松找到解决方案。

注意:使用 InterlockedDecrement 让我假设您正在 Windows 上工作。

记录一切

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

  1. 记录构造,包括 this 指针值和其他相关数据
  2. 记录破坏,包括this 指针值和其他相关数据

这样,您将能够查看 this 是否被释放两次,甚至根本没有分配。

...一切,包括堆栈

我的问题发生在托管 C++/.NET 代码中,这意味着我可以轻松访问堆栈,这是一件幸事。您似乎在使用纯 C++,因此检索堆栈可能是一件苦差事,但它仍然非常有用。

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

请注意,您需要处于调试版本,或者将 PDB 文件与可执行文件一起使用,以确保堆栈被完全打印。

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

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

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

您的崩溃与线程相关吗?

最后但并非最不重要的一点是,“我只发生了 5% 的时间”症状可能是由不同的代码路径执行引起的,或者是多个线程一起处理相同的数据。

InterlockedDecrement 部分让我烦恼:是你的对象生活在多个线程中吗? m_nRefCount 是否正确对齐且易失性 LONG

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

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

对于未在 32 字节边界上对齐的变量也是如此。你的代码中有#pragma pack()指令吗?您的 projet 文件是否更改了默认对齐方式(我假设您正在使用 Visual Studio)?

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

Crashes upon deallocation can be a pain: It is not supposed to happen, and when it happens, the code is too complicated to easily find a solution.

Note: The use of InterlockedDecrement have me assume you are working on Windows.

Log everything

My own solution was to massively log the construction/destruction, as the crash could well never happen while debugging:

  1. Log the construction, including the this pointer value, and other relevant data
  2. Log the destruction, including the this pointer value, and other relevant data

This way, you'll be able to see if the this was deallocated twice, or even allocated at all.

... everything, including the stack

My problem happened in Managed C++/.NET code, meaning that I had easy access to the stack, which was a blessing. You seem to work on plain C++, so retrieving the stack could be a chore, but still, it remains very very useful.

You should try to load code from internet to print out the current stack for each log. I remember playing with http://www.codeproject.com/KB/threads/StackWalker.aspx for that.

Note that you'll need to either be in debug build, or have the PDB file along the executable file, to make sure the stack will be fully printed.

... everything, including multiple crashes

I believe you are on Windows: You could try to catch the SEH exception. This way, if multiple crashes are happening, you'll see them all, instead of seeing only the first, and each time you'll be able to mark "OK" or "CRASHED" in your logs. I went even as far as using maps to remember addresses of allocations/deallocations, thus organizing the logs to show them together (instead of sequentially).

I'm at home, so I can't provide you with the exact code, but here, Google is your friend, but the thing to remember is that you can't have a __try/__except handdler everywhere (C++ unwinding and C++ exception handlers are not compatible with SEH), so you'll have to write an intermediary function to catch the SEH exception.

Is your crash thread-related?

Last, but not least, the "I happens only 5% of the time" symptom could be caused by different code path executions, or the fact you have multiple threads playing together with the same data.

The InterlockedDecrement part bothers me: Is your object living in multiple threads? And is m_nRefCount correctly aligned and volatile LONG?

The correctly aligned and LONG part are important, here.

If your variable is not a LONG (for example, it could be a size_t, which is not a LONG on a 64-bit Windows), then the function could well work the wrong way.

The same can be said for a variable not aligned on 32-byte boundaries. Is there #pragma pack() instructions in your code? Does your projet file change the default alignment (I assume you're working on Visual Studio)?

For the volatile part, InterlockedDecrement seem to generate a Read/Write memory barrier, so the volatile part should not be mandatory (see http://msdn.microsoft.com/en-us/library/f20w0x5e.aspx).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文