I am working in a DLL which sometimes raises unhandled exceptions. I am using madExcept to detect and debug the buggy code, but when I finally deploy my DLL I want include my own global exception handler inside the DLL to log the exceptions.
So the question is how I can set a global exception handler in my Delphi DLL?
The concept of "a global exception handler" doesn't really exist in DLLs the way it exists in the VCL. To understand why, remember that exceptions propagate by unwinding the stack until they can find a handler. The VCL can install a global exception handler because in a VCL app, everything that happens (excluding startup and shutdown) will have TApplication.Run
somewhere in the call stack, and that's where it puts the exception handler. Since your DLL doesn't have a single central point like that, you can't do it that way.
What you can do is set up a "central exception handler routine" in your DLL somewhere. It should take an Exception
object as a parameter. Then do something like this for all your exported routines:
procedure MyExportedRoutine(param: integer);
begin
try
//do normal stuff
except
on E: Exception do
CentralExeptionHandler(E);
end;
end;
That's really the best you can do, unless you're using COM. If you're writing a COM DLL, mark your interface methods with the safecall
calling convention and the compiler will silently generate code for you that takes care of exception propagation.
What exactly do you mean by "global exception handler"?
Windows Structured Exception Handling (SEH), in 32-bit, finds a handler by walking the exception handler chain of the thread in which the exception occurred. The exception handler chain is a linked list of records, the head of which is found in FS:[0]
; the records are normally allocated on the stack, pushed at every try
and popped when the protected block is exited. There's a callback routine referred to by each exception record; Windows calls this routine with details of the exception during its search phase to determine whether or not this "level" of the chain is going to "handle" the exception. Windows then unwinds the call stack to that point by going through the exception chain again, calling each callback with a different value letting it know that unwinding is going on, until it reaches the handler that elected to handle the exception. If no handler is found, the process is terminated, hard, without notification. Normally this doesn't happen; the OS installs a last-chance handler of its own at the bottom of the stack (last element in the chain), and this normally pops up the familiar Windows "this program has encountered a problem" dialog. But if things have gotten very corrupt, or the exception handler chain has been messed around with to remove it, then the process goes down hard.
So from this brief overview of Windows exception handling, it should be clear that there is no single "global" handler, only a list of handlers, one list per thread (FS
register is part of the thread context); and the "last chance" handler is the one that is installed earliest in the stack. The easiest way of catching exception that occur inside your DLL is to immediately install an exception handler at every entry point. See Mason's answer for details of how to do that (it's with try
/except
); but be aware that if your DLL calls back into somewhere else (e.g. via a callback routine), then you may be catching exceptions that weren't "meant" for you and not caused by your code. (It's poor style to expect exceptions to propagate like that through third-party code at the DLL level, but it can happen.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With