我遇到了典型的访问冲突:
access violation at 0x4ebb7456: read of address 0x4ebb7456
这发生在程序的其余部分已经关闭时创建的线程中。
发生异常时主线程正在运行System.FinalizeUnits
。
我发现该地址属于加载gdiplus.dll
的内存区域。
如果我向 dpr 文件添加 LoadLibrary('gdiplus.dll')
调用而不在返回的句柄上调用 FreeLibrary
,问题就会消失,这样在运行终结部分时不会卸载 gdiplus.dll
。
如何找出程序的哪一部分创建了导致访问冲突的线程?
有没有办法识别调用已释放内存空间的代码?
FastMM 和 madExcept 帮助不大,显示 madExcept 错误报告窗口,但立即再次关闭并且不写入日志文件。
我可以将程序拆开,但它是一个不平凡的应用程序,我宁愿使用某种调试技术来解决这个问题。
最佳答案
追踪此问题的第一步可能是检测代码的哪一部分实际创建了线程。在应用程序关闭期间创建线程对我来说听起来就像是坏消息,因此我希望确保这种情况不会发生。
至于如何做到这一点,我会使用调试器断点。首先,我在 Windows.pas 中的 CreateThread
实现上设置断点,并使用调试 DCU 运行。查看该断点是否在关闭期间触发。
如果它在关闭期间没有中断,则该线程是由非 Delphi 代码创建的。我的下一步是打开 CPU View 并进入 CreateThread。 CreateThread
的反汇编将从 JMP
指令开始。进入此页面,您将进入 kernel32.CreateThread
。现在在此处设置一个断点,看看当您在关闭期间触发此断点时,调用堆栈是什么。
关于delphi - 如何找出哪些代码调用了已经卸载的模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6899629/