gpt4 book ai didi

delphi - 什么会导致 delete 循环 Sleep()ing 并且永远不会在 Borland/Embarcadero RTL 中返回?

转载 作者:行者123 更新时间:2023-12-03 18:49:44 24 4
gpt4 key购买 nike

我有一个奇怪的错误,当删除一个特定对象时,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 事件处理程序,一个微调框刚刚更改,一个设置对象更新,并且它所做的临时设置正在被删除:
delete poNewSettings;

这段代码一两年没有改变,设置类也有一段时间没有改变,它基本上是一个包含许多设置的巨大的类似结构的对象。它有一个编译器生成的析构函数。单步执行代码显示了许多删除字符串和其他 std::对象的调用,然后在单步执行下一个函数时(即在 ~basic_string() 结束时,在右大括号 } 处按 F7 ),它似乎卡住了,这IDE 从不显示。卡住是它在 Sleep() 中。此代码在主线程中运行。

我尝试使用 CPU View 来推断调用 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 毫秒唤醒一次(从 sleep 中返回);我没有看到(还没有!)它如何影响另一个线程的 delete

据我所知,没有其他线程正在删除或分配任何东西。我在 CC32100MT._mallocCC32100MT._freeCC32100MT._realloc 中放置了断点。运行时没有其他线程中断,当暂停检查时,没有其他线程在任何这些调用中。

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

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

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

最佳答案

在这种情况下,我不能 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 中捕获到严重异常后代码的结果,中止您的线程正在执行的任何操作,并且基本上现在什么都不做,直到您的进程终止。我要调试的第一个地方是单步执行析构函数的代码并查看它的作用。

关于delphi - 什么会导致 delete 循环 Sleep()ing 并且永远不会在 Borland/Embarcadero RTL 中返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15298997/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com