什么可以导致删除循环Sleep()ing并且永远不会返回Borland / Embarcadero RTL?

时间:2013-03-08 16:41:41

标签: delphi memory sleep c++builder fastmm

我有一个奇怪的错误,当删除一个特定对象时,delete永远不会返回。相反,它似乎花时间在永久循环中调用Sleep()。这是调用堆栈:

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

正在运行,它会返回SysFreeMem(永远不会回到free)并再次从Sleep内调用SysFreeMem,永久循环播放。

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

delete poNewSettings;

此代码在一年或两年内没有更改,也没有设置类一段时间,这基本上是一个包含大量设置的巨型类似结构的对象。它有一个编译器生成的析构函数。单步执行代码会显示删除字符串和其他std ::对象的一些调用,然后在进入下一个函数时(即~basic_string()结束时,它会在关闭大括号时按F7)冻结}),IDE从未显示过。冻结是它在Sleep()内部。此代码在主线程中运行。

我尝试使用CPU视图来推断Sleep()被调用的延迟,但是无法发现它 - 我不是完全依赖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再次检查。分配和free是用于文件夹路径的字符串。虽然程序中还有其他线程,但它们都被阻止等待某事做,这次是使用WaitForSingleObject或类似的。这个后台任务线程每100ms唤醒一次(从Sleep返回);我还没看到(还有!)它如何影响另一个帖子delete

据我所知,没有其他线程正在删除或分配任何内容。我在CC32100MT._mallocCC32100MT._freeCC32100MT._realloc中添加了断点。没有其他人在运行时中断,当暂停检查时,其中任何一个呼叫都没有其他线程。

删除循环而不返回的原因是什么?

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

我添加了Delphi标签,因为它使用的是Embarcadero RTL和FastMM,Delphi人员使用它比C ++人员更多。

1 个答案:

答案 0 :(得分:0)

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

我认为您应该进入发生这种情况的地方,然后检查您正在释放的变量并查看它是否已损坏。

如果您正在释放的变量是您自己定义的类,我通常希望将Guard字段添加到对象的开头和结尾。

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

在构造函数中,我将防护设置为我在某处定义的MAGIC1和MAGIC2, 在析构函数中,我将守卫设置为MAGIC_FREE_1和MAGIC_FREE_2。

然后我可以看看我是否重复了同一个对象的破坏,或者是否有其他东西覆盖了那个位置的堆内存。

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