我的代码在删除此代码时崩溃
尝试删除它时出现分段错误。
我知道你想删除这个,但它是我的前任留下的。我知道我应该采取的一些预防措施 ,这些都已经过验证并得到处理。
我不知道什么样的情况可能会导致这次崩溃,只是偶尔发生一次。大约 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
最明显的答案是:不要删除它。
如果您坚持这样做,请使用常见的方法来查找错误:
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)
看来您的
new
和delete
不匹配。请注意,delete this;
只能用于使用new
分配的对象(并且在覆盖operator new
的情况下,或多个副本C++ 运行时的特定new
与当前作用域中找到的delete
相匹配)It seems like you've mismatched
new
anddelete
. Note thatdelete this;
can only be used on an object which was allocated usingnew
(and in case of overriddenoperator new
, or multiple copies of the C++ runtime, the particularnew
that matchesdelete
found in the current scope)释放时的崩溃可能会很痛苦:这种情况不应该发生,而当它发生时,代码太复杂而无法轻松找到解决方案。
注意:使用
InterlockedDecrement
让我假设您正在 Windows 上工作。记录一切
我自己的解决方案是大量记录构造/破坏,因为调试时崩溃很可能永远不会发生:
this
指针值和其他相关数据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:
this
pointer value, and other relevant datathis
pointer value, and other relevant dataThis 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 andvolatile
LONG
?The correctly aligned and
LONG
part are important, here.If your variable is not a
LONG
(for example, it could be asize_t
, which is not aLONG
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 thevolatile
part should not be mandatory (see http://msdn.microsoft.com/en-us/library/f20w0x5e.aspx).