2013-03-08 62 views
2

我有一个奇怪的错误,当删除一个特定的对象时,delete永远不会返回。相反,它似乎花时间在永久循环中呼叫Sleep()。这里的调用堆栈:什么会导致删除循环睡眠()并且永远不会返回Borland/Embarcadero RTL?

:7723fd71 ntdll.ZwDelayExecution + 0x15 
:767c4498 KERNELBASE.Sleep + 0xf 
:21495359 [email protected]@SysFreeMem$qqrpv + 0xb5 
:32aaa3e5 CC32100MT._free + 0xd 
:32a020b2 [email protected]$bdele$qpv + 0x1e 
[My code] 

运行时,它返回到SysFreeMem(永不回free)和SysFreeMem内再次呼吁Sleep,永久循环。

我的代码非常简单:它是一个VCL事件处理程序,一个纺纱器刚刚更改和设置对象更新,它所做的临时设置被删除:

delete poNewSettings; 

此代码并没有改变一两年,也没有一段时间的设置类,这基本上是一个巨大的结构类对象包含大量的设置。它有一个编译器生成的析构函数。逐句通过代码显示了一些删除字符串和其他std :: objects的调用,然后在进入下一个函数时(即在~basic_string()的末尾按下F7,在关闭大括号}处),它似乎冻结IDE从不显示。冻结是它在Sleep()内。此代码正在主线程中运行。我试图使用CPU视图来推断睡眠()被调用的延迟,但无法发现它 - 我不完全放在x86汇编代码,恐怕。

另一个线程在Sleep之内,可能与COM有关(应用程序是一个COM服务器,尽管目前没有使用COM)。它的整个调用堆栈是:

:7723fd71 ntdll.ZwDelayExecution + 0x15 
:767c4498 KERNELBASE.Sleep + 0xf 
:74c7d98d ; C:\Windows\syswow64\ole32.dll 
:74c7d87a ; C:\Windows\syswow64\ole32.dll 
:768133aa kernel32.BaseThreadInitThunk + 0x12 
:77259ef2 ntdll.RtlInitializeExceptionChain + 0x63 
:77259ec5 ntdll.RtlInitializeExceptionChain + 0x36 

另外一个线程正在做一些积极分配和释放内存,并呼吁Sleep()太 - 后台任务运行它检查是否需要工作(它不必)并且睡眠100ms再次检查。分配和空闲是用于文件夹路径的字符串。虽然程序中还有其他线程,但它们都被阻塞等待某些事情发生,这次使用的是WaitForSingleObject或类似的。该后台任务线程每100ms唤醒一次(从睡眠中返回);我没有看到(还!)它是如何影响另一个线程的delete

据我所知,没有其他线程正在删除或分配任何东西。我在CC32100MT._malloc,CC32100MT._freeCC32100MT._realloc中加入了断点。运行时没有其他人中断,并且在暂停检查时,其他任何线程都不在其中。

什么可能是删除循环和不返回的原因?

我正在使用: * RAD Studio 2010,完全更新 *应用程序主要是C++(C++ Builder),带有小的Delphi位。 *因为它使用了Embarcadero的RTL,我认为它是使用FastMM

我已经因为它使用Embarcadero公司RTL和FastMM,这是由德尔福的人比用C++的人多了不少使用添加了德尔福标签。

+1

听起来好像你可能在堆空闲块列表中有一个循环循环的堆损坏。我对C++ Builder不熟悉 - 你能够启用FastMM调试标志吗? – 2013-03-08 18:03:58

+0

感谢您的建议!我不确定FastMM调试模式。我*认为它使用fastMM的C实现 - 我以前在RTL源文件夹中看到过一个 - 而不是Delphi实现。坦率地说,我不太了解内部结构。 – 2013-03-08 18:09:29

回答

0

我不是100%确定在这种情况下,您可以信任RAD Studio IDE中的调试器,以正确命名涉及的内核符号。

我想你应该踏进这个地方发生的地方,然后检查你正在释放变量,看看它是否已被损坏。

如果你释放的变量是你自己定义我通常喜欢保护字段添加到对象的开头和结尾的类。

class TMyPOSettings { 
    public: 
    ... 
    private: 
    int Guard1; 
    // all my other instance data 
    int Guard2 
}; 

在构造函数中我设置了警卫MAGIC1和MAGIC2我某处定义, 和析构函数中我设置了警卫MAGIC_FREE_1和MAGIC_FREE_2。

然后我可以看到,如果我重复同一个对象的破坏,或者一些其他的事情是在那个位置覆盖我的堆内存。

我不知道是否有可能你正在调试的是事实上是在Windows内部发现了一个严重的异常之后代码的结果,中止了你的线程正在做的任何事情,并且现在基本上什么都不做,直到你的进程终止。我要调试的第一个地方是单步执行析构函数的代码并查看它的功能。

+0

谢谢沃伦。据我可以告诉它没有损坏(并且它只创建了两行以上!)我将继续调查...... – 2013-03-28 11:24:25

相关问题