I got a typical access violation:
access violation at 0x4ebb7456: read of address 0x4ebb7456
This happens in a thread that is created when the rest of the program is already shutting down.
The main thread is running System.FinalizeUnits
at the time of the exception.
I found out that the adress belongings to a memory region where gdiplus.dll
was loaded.
The problem goes away if I add a LoadLibrary('gdiplus.dll')
call to the dpr file without calling FreeLibrary
on the returned handle, this way the gdiplus.dll
is not unloaded while the finalization sections are run.
How do I find out which part of the program creates the thread leading to the access violation?
Is there a way to identify the code that calls into the freed memory space?
FastMM and madExcept are of little help, the madExcept error report window shows up, but is immediatly closed again and doesn't write a log file.
I could tear the program apart, but it's a non trivial application and I'd rather solve this us开发者_高级运维ing some kind of debugging technique.
Probably the first step to tracing this is to detect what part of your code actually creates the thread. Creating a thread during application shutdown sounds to me like bad news in the making so I'd be looking to make sure that simply doesn't happen.
As for how to do it, I'd use debugger breakpoints. First of all I'd set a breakpoint on the implementation of CreateThread
in Windows.pas and run with debug DCUs. See if that breakpoint triggers during shutdown.
If it doesn't break in there during shutdown then the thread is created by non-Delphi code. My next step would be to open the CPU view and step into CreateThread
. The disassembly for CreateThread
will start with a JMP
instruction. Step into this and you will be at kernel32.CreateThread
. Now set a breakpoint here and see what the call stack is when you trigger this during shutdown.
I would find the unit that is loading the library (possibly it's a component that you are using) and add it to the top (or near the top) of your project file. This will ensure that it is unloaded later in the shutdown of your application, and should prevent the AV.
So, for instance, if you are using GdiPlus, you would end up with something like this:
program MyProgram;
uses
FastMM4,
GdiPlus, // <=== this line inserted
Windows,
Forms,
Controls,
Classes,
This will possibly mask a problem that may come back to bight you later. It's worth trying to work out which unit is trying to call into the unloaded DLL as well as doing this.
精彩评论