【发布时间】:2013-02-24 07:01:33
【问题描述】:
我有一个奇怪的错误,当删除一个特定对象时,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)并再次从SysFreeMem 内部调用Sleep,永久循环。
我的代码非常简单:它是一个 VCL 事件处理程序,一个旋转框刚刚更改,一个设置对象更新,它所做的临时设置正在被删除:
delete poNewSettings;
这段代码已经一两年没有改变了,设置类也有一段时间没有改变,它基本上是一个包含许多设置的巨大的类似结构的对象。它有一个编译器生成的析构函数。单步执行代码显示了一些删除字符串和其他 std:: 对象的调用,然后在单步执行下一个函数时(即在 ~basic_string() 的末尾,在右大括号 @987654330 处按 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() - 一个后台任务正在运行,它正在检查它是否需要工作(它不必)并且正在休眠 100 毫秒以检查再次。分配和免费用于文件夹路径的字符串。虽然程序中还有其他线程,但它们都被阻塞等待做某事,这次使用WaitForSingleObject 或类似的。此后台任务线程每 100 毫秒唤醒一次(从睡眠中返回);我没有看到(还没有!)它如何影响另一个线程的delete。
据我所知,没有其他线程正在删除或分配任何内容。我在CC32100MT._malloc、CC32100MT._free 和CC32100MT._realloc 中设置了断点。运行时没有其他线程中断,当暂停检查时,这些调用中没有其他线程。
删除循环而不返回的原因可能是什么?
我正在使用: * RAD Studio 2010,全面更新 * 应用程序主要是 C++ (C++ Builder) 和少量的 Delphi。 * 因为它使用的是 Embarcadero RTL,所以我认为它使用的是 FastMM
我添加了 Delphi 标记,因为它使用 Embarcadero RTL 和 FastMM,Delphi 人比 C++ 人使用更多。
【问题讨论】:
-
听起来你可能在空闲堆块列表中出现了堆损坏,并出现了循环循环。我不熟悉 C++Builder - 你能从那里启用 FastMM 调试标志吗?
-
感谢您的建议!我不确定 FastMM 调试模式。我认为它使用了 fastMM 的 C 实现——我之前在 RTL 源文件夹中看到过一个——而不是 Delphi 实现。坦率地说,我对内部结构了解得不够多。
标签: delphi memory sleep c++builder fastmm