Try - except not displaying Exception error message [duplicate] - delphi

I've set Application.OnException to a custom exception handler so that I can log crashes and give an option to exit. However, I'm now finding that this runs even on exceptions that I've already handled, for instance, exceptions that come up when validating number inputs. Is there a way to have the custom exception handler only run on unhandled exceptions?
Edit: it turns out that I get the expected behavior when I run outside the debugger. Maybe it's just a debugger thing. I do not find the Delphi debugger's interaction with exceptions to be intuitive, to say the least.

If behavior changes inside and outside the debugger, then it's not really your program that's telling you about exceptions. I've written about this phenomenon on my Web site:
Why do I continue getting error messages even after I have written an exception handler?
An excerpt:
In its default settings, the Delphi IDE notifies you whenever an exception occurs in your program ... . What’s important to realize is that at that point, none of your program’s exception-handling code has run yet. It’s all Delphi itself; its special status as a debugger allows it to get first notification of any exception in your program, even before your program knows about it.
After you dismiss Delphi’s message box, execution will be paused at the best line of your source code Delphi could find to represent the source of the exception. Press the “Run” button to have your program resume. Control will pass to the next finally or except
block. Before you resume your program, you may use the various debugging tools at your disposal. You can inspect the values of any variables in scope, and you can even modify their values.
So, how do you notify Delphi that you've already handled an exception? You don't — because your program hasn't handled it yet. And why can't the debugger detect whether your program is going to handle an exception? Because in order to do that, it needs to execute your program further. Detecting the lack of an exception handler is like solving the halting problem. The only way to determine whether an exception is going to be handled is to let the program run and then see whether the exception gets handled. But by that point, it's too late to do any debugging, so the debugger has no choice but to pause your program when it first detects an exception and then let you figure out what to do from there.
My article goes on to describe some ways you can avoid having the debugger catch certain exceptions, summarized here:
Use advanced breakpoints to temporarily disable breaking on exceptions for certain regions of the code.
Configure the debugger to ignore certain classes of exceptions (and their descendants).
Tell the debugger not to notify you about any exceptions.
Disable integrated debugging altogether.
There's another options that I didn't include in my article:
Change your program such that the exception doesn't get raised in the first place.
You say you're validating numeric input. That sounds to me like you're doing something like calling StrToInt and then catching the EConvertError exception when the input isn't a valid integer. That's an expensive way of validating input. Instead of that, use TryStrToInt, which will tell you whether the conversion succeeded, or StrToIntDef, which will silently return a default value instead of raising an exception. Another option is plain old Val, which tries to convert a string, and if it fails, it tells you which position in the string caused the failure. Val is particularly useful if you want to consume as many characters as possible for the conversion and then resume parsing at the next non-numeric character.

Quoting from the documentation (Delphi 7) on TApplication.OnException
"Use OnException to change the default behavior that occurs when an exception is not
handled by application code."
So: Only unhandled exception will be available in the OnException event handler. What you are experiencing is probably the Delphi IDE breaking on the exception. This is (at least in Delphi 7) configurable.
In Delphi 7 you can configure it by clicking on the Tools->Debugger Options menu. Then select the "Language Exceptions" an un-ckech the "Stop on Delphi exceptions" checkbox. It might however be different in other delphi versions.

An alternative might be to not use Application.OnException. But to simply catch all exceptions in your "main" function. That way you can catch all exceptions you have not cached before, log the exception, and then crash.

Application.OnException should only fire for unhandled exceptions. Re-raising an exception in a try-except block will cause the exception to be handled by Application.OnException. For input validation that raises an exception, you could display a message to the user and then re-raise the exception only if you want it recorded into the error log.

Related

Delphi effective way to handle socket error [duplicate]

I've set Application.OnException to a custom exception handler so that I can log crashes and give an option to exit. However, I'm now finding that this runs even on exceptions that I've already handled, for instance, exceptions that come up when validating number inputs. Is there a way to have the custom exception handler only run on unhandled exceptions?
Edit: it turns out that I get the expected behavior when I run outside the debugger. Maybe it's just a debugger thing. I do not find the Delphi debugger's interaction with exceptions to be intuitive, to say the least.
If behavior changes inside and outside the debugger, then it's not really your program that's telling you about exceptions. I've written about this phenomenon on my Web site:
Why do I continue getting error messages even after I have written an exception handler?
An excerpt:
In its default settings, the Delphi IDE notifies you whenever an exception occurs in your program ... . What’s important to realize is that at that point, none of your program’s exception-handling code has run yet. It’s all Delphi itself; its special status as a debugger allows it to get first notification of any exception in your program, even before your program knows about it.
After you dismiss Delphi’s message box, execution will be paused at the best line of your source code Delphi could find to represent the source of the exception. Press the “Run” button to have your program resume. Control will pass to the next finally or except
block. Before you resume your program, you may use the various debugging tools at your disposal. You can inspect the values of any variables in scope, and you can even modify their values.
So, how do you notify Delphi that you've already handled an exception? You don't — because your program hasn't handled it yet. And why can't the debugger detect whether your program is going to handle an exception? Because in order to do that, it needs to execute your program further. Detecting the lack of an exception handler is like solving the halting problem. The only way to determine whether an exception is going to be handled is to let the program run and then see whether the exception gets handled. But by that point, it's too late to do any debugging, so the debugger has no choice but to pause your program when it first detects an exception and then let you figure out what to do from there.
My article goes on to describe some ways you can avoid having the debugger catch certain exceptions, summarized here:
Use advanced breakpoints to temporarily disable breaking on exceptions for certain regions of the code.
Configure the debugger to ignore certain classes of exceptions (and their descendants).
Tell the debugger not to notify you about any exceptions.
Disable integrated debugging altogether.
There's another options that I didn't include in my article:
Change your program such that the exception doesn't get raised in the first place.
You say you're validating numeric input. That sounds to me like you're doing something like calling StrToInt and then catching the EConvertError exception when the input isn't a valid integer. That's an expensive way of validating input. Instead of that, use TryStrToInt, which will tell you whether the conversion succeeded, or StrToIntDef, which will silently return a default value instead of raising an exception. Another option is plain old Val, which tries to convert a string, and if it fails, it tells you which position in the string caused the failure. Val is particularly useful if you want to consume as many characters as possible for the conversion and then resume parsing at the next non-numeric character.
Quoting from the documentation (Delphi 7) on TApplication.OnException
"Use OnException to change the default behavior that occurs when an exception is not
handled by application code."
So: Only unhandled exception will be available in the OnException event handler. What you are experiencing is probably the Delphi IDE breaking on the exception. This is (at least in Delphi 7) configurable.
In Delphi 7 you can configure it by clicking on the Tools->Debugger Options menu. Then select the "Language Exceptions" an un-ckech the "Stop on Delphi exceptions" checkbox. It might however be different in other delphi versions.
An alternative might be to not use Application.OnException. But to simply catch all exceptions in your "main" function. That way you can catch all exceptions you have not cached before, log the exception, and then crash.
Application.OnException should only fire for unhandled exceptions. Re-raising an exception in a try-except block will cause the exception to be handled by Application.OnException. For input validation that raises an exception, you could display a message to the user and then re-raise the exception only if you want it recorded into the error log.

Exception breakpoints in xcode for iOS, is exceptions excusable?

Am new to the iOS development. While looking into one of the App I work on, with exception breakpoint enabled in xcode. I see so many repetitive exceptions been raised.
But till now, we never realised this, as iOS was excusing those exceptions. The main exception was happening in our service layer, where, in an XML parsing, one of the element mentioned as key was missing. since so many back end requests are fired, for every XML response, and for multiple items inside it, this exception is thrown.
Now that our app is published, will this impact the device's stability? We are planning to fix thee kind of issues. But now, Will these be logged into Apple's diagnostic information. Just curious to know these. Can someone shed some light over it?
In Objective-C, Exceptions are used to signal fatal errors, that is programmer errors and "unexpected" and unrecoverable runtime errors. In Objective-C, Exceptions are a debugging and testing aid, not a construct to control program flow or to regain control after an error.
Usually, an application in a release state shouldn't throw exceptions. If it happens anyway, the only correct course of action is to terminate the program as soon as possible. In general, the Objective-C system frameworks are not exception safe. This means, after an exception has been thrown the application's state will be corrupt. If your program continues, even worse things may happen.
There are only a few, always undocumented harmless cases where exceptions will be thrown and caught by system libraries without leaving the program in an unstable condition.
See also https://developer.apple.com/library/ios/documentation/cocoa/conceptual/Exceptions/Exceptions.html

How I can create a global exception handler in a DLL?

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.)

How do I let Delphi know I've already handled an exception?

I've set Application.OnException to a custom exception handler so that I can log crashes and give an option to exit. However, I'm now finding that this runs even on exceptions that I've already handled, for instance, exceptions that come up when validating number inputs. Is there a way to have the custom exception handler only run on unhandled exceptions?
Edit: it turns out that I get the expected behavior when I run outside the debugger. Maybe it's just a debugger thing. I do not find the Delphi debugger's interaction with exceptions to be intuitive, to say the least.
If behavior changes inside and outside the debugger, then it's not really your program that's telling you about exceptions. I've written about this phenomenon on my Web site:
Why do I continue getting error messages even after I have written an exception handler?
An excerpt:
In its default settings, the Delphi IDE notifies you whenever an exception occurs in your program ... . What’s important to realize is that at that point, none of your program’s exception-handling code has run yet. It’s all Delphi itself; its special status as a debugger allows it to get first notification of any exception in your program, even before your program knows about it.
After you dismiss Delphi’s message box, execution will be paused at the best line of your source code Delphi could find to represent the source of the exception. Press the “Run” button to have your program resume. Control will pass to the next finally or except
block. Before you resume your program, you may use the various debugging tools at your disposal. You can inspect the values of any variables in scope, and you can even modify their values.
So, how do you notify Delphi that you've already handled an exception? You don't — because your program hasn't handled it yet. And why can't the debugger detect whether your program is going to handle an exception? Because in order to do that, it needs to execute your program further. Detecting the lack of an exception handler is like solving the halting problem. The only way to determine whether an exception is going to be handled is to let the program run and then see whether the exception gets handled. But by that point, it's too late to do any debugging, so the debugger has no choice but to pause your program when it first detects an exception and then let you figure out what to do from there.
My article goes on to describe some ways you can avoid having the debugger catch certain exceptions, summarized here:
Use advanced breakpoints to temporarily disable breaking on exceptions for certain regions of the code.
Configure the debugger to ignore certain classes of exceptions (and their descendants).
Tell the debugger not to notify you about any exceptions.
Disable integrated debugging altogether.
There's another options that I didn't include in my article:
Change your program such that the exception doesn't get raised in the first place.
You say you're validating numeric input. That sounds to me like you're doing something like calling StrToInt and then catching the EConvertError exception when the input isn't a valid integer. That's an expensive way of validating input. Instead of that, use TryStrToInt, which will tell you whether the conversion succeeded, or StrToIntDef, which will silently return a default value instead of raising an exception. Another option is plain old Val, which tries to convert a string, and if it fails, it tells you which position in the string caused the failure. Val is particularly useful if you want to consume as many characters as possible for the conversion and then resume parsing at the next non-numeric character.
Quoting from the documentation (Delphi 7) on TApplication.OnException
"Use OnException to change the default behavior that occurs when an exception is not
handled by application code."
So: Only unhandled exception will be available in the OnException event handler. What you are experiencing is probably the Delphi IDE breaking on the exception. This is (at least in Delphi 7) configurable.
In Delphi 7 you can configure it by clicking on the Tools->Debugger Options menu. Then select the "Language Exceptions" an un-ckech the "Stop on Delphi exceptions" checkbox. It might however be different in other delphi versions.
An alternative might be to not use Application.OnException. But to simply catch all exceptions in your "main" function. That way you can catch all exceptions you have not cached before, log the exception, and then crash.
Application.OnException should only fire for unhandled exceptions. Re-raising an exception in a try-except block will cause the exception to be handled by Application.OnException. For input validation that raises an exception, you could display a message to the user and then re-raise the exception only if you want it recorded into the error log.

How can I find out which exceptions a Delphi function might throw?

Is there a good way to find out which exceptions a procedure/function can raise in Delphi (including it's called procedures/functions)?
In Java you always have to declare which exceptions that can be thrown, but this is not the case in Delphi, which could lead to unhandled exceptions.
Are there any code analysis tools that detects unhandled exceptions?
(Edit: It is now obvious that the question referred only to design-time checking.)
New answer:
I cannot state whether there are any tools to check this for you. Pascal Analyzer, for one, does not.
I can tell you, however, that in most Delphi applications, even if there was a tool to check this for you, you would get no results.
Why? Because the main message loop in TApplication.Run() wraps all HandleMessage() calls in an exception handling block, which catches all exception types. Thus you will have implicit/default exception handling around 99.999% of code in most applications. And in most applications, this exception handling will be around 100% of your own code - the 0.001% of code which is not wrapped in exception handling will be the automatically generated code.
If there was a tool available to check this for you, you would need to rewrite Application.run() such that it does not include exception handling.
(Previous answer:
The Application.OnException event handler can be assigned to catch all exceptions that aren't handled by other exception handlers. Whilst this is run-time, and thus perhaps not exactly what you are after (it sounds like you want to identify them at design time), it does allow you to trap any exception not handled elsewhere. In conjunction with tools such as the JCLDebug stuff in the Jedi Code Library, you could log a stack trace to find out where & why an exception occurred, which would allow for further investigation and adding specific exception handling or prevention around the guilty code...)
My guess is that you're trying to make Delphi behave like Java, which is not a good approach. I'd advise not to worry too much about unhandled exceptions. In the worst case, they'll bubble up to the generic VCL exception handler and cause a Windows message dialog. In a normal application, they won't halt the application.
Well-written code would document the different exceptions that can be raised so you can handle them in a meaningful way. Catch-all handlers aren't recommended since there is really no way to know what to do if you don't know why an exception was raised. I can also highly recommend madExcept.
Except for a scan on the "raise" keyword, there's no language construct in Delphi that tells the casual reader which exceptions can be expected from a method.
At runtime, one could add a catch-all exception handler in every method, but that's not advisable, as it will slow down the speed of execution. (And it's cumbersome to do too).
Adding an exception-handling block to a method will add a few assembly instructions to it (even when the exception isn't triggered), which forms measureable slow-down when the method is called very often.
There do exist a few libraries that can help you in analyzing runtime exceptions, like madExcept, JclDebug, and EurekaLog. These tools can log all kinds of details about the exception, it's highly advisable to use one of those!
The short answers is there is no tool that does what you say, and even a scan for the raise keyword wouldn't get you there. EAccessViolation or EOutOfMemory are just two of a number of exceptions that could get raised just about anywhere.
One fundamental thing about Delphi is the exceptions are hierarchical: All defined language exceptions descend from Exception, although it is worth noting that it is actually possible to raise any TObject descendant.
If you want to catch every exception that is raised in a particular procedure, just wrap it in a try / except block, but as was mentioned this is not recommended.
// Other code . . .
try
SomeProcedure()
except // BAD IDEA!
ShowMessage('I caught them all!');
end;
That will catch everything, even instances of a raised TObject. Although I would argue that this is rarely the best course of action. Usually you want to use a try / finally block and then allow your global exception handler (or one final try / except block) to actually handle the exceptions.
I will second (or is it third) MadExcept. I have been using it successfully in several commercial applications without any problems. The nice thing about MadExcept is that it will generate a report for you with a full stack trace that will generally point you in the right direction as to what went wrong, and can even include a screenshot, as well has have this automatically emailed to you from the clients computer with a simple mouse click.
However, you don't want to use this for ALL exceptions, just to catch the ones you miss. For instance, if you open a database and the login fails, it would be better for you to catch and handle this one yourself rather than give the user the MadExcept default error in your application occured message.
Any exception not explicitly or generally handled at a specific level will trickle upwards in the call stack. The Delphi RTL (Run Time Library) will generate a set of different exception classes - (mathematical errors, access errors, class specific errors etc). You can chose to handle them specifically or generally in the different try except blocks.
You don't really need to declare any new exception classes unless you need to propagate a specific functional context with the exception.
As previous commenters wrote, you can also add a mother of all exception handlers like MadExcept or EurekaLog to catch the uncaught.
edit: This is a blanket insurance against unhandled exceptions
try
ThisFunctionMayFail;
except
// but it sure won't crash the application
on e:exception
do begin
// something sensible to handle the error
// or perhaps log and/or display the the generic e.description message
end
end;
Take a look at http://www.madshi.net/madExceptDescription.htm
For runtime try Eurekalog. I do not know whether a tool exists for design time. You will have more dificoulties even when you have third party code without source. There is no need in Delphi to catch exceptions, so you do not have to declare them like in Java.
What I wanted to say is that Delphi does not require that an exception is handled. It will just terminate the program. EurekaLog provides means to log handled and unhandled exceptions and provide a wealth of information on the sate of the program when the exception occured, including the line of code it occured at and the call stack at the time.
As Jim McKeeth points out, you can't get a definitive answer, but it seems to me that one could partially answer the question by some static analysis: given a particular function/procedure, construct a call graph. Check each of the functions in that call graph for a raise statement. That would tell you, for instance, that TIdTcpClient.ReadString can raise an EIdNotConnected (among others).
A clever analyser might also note that some code uses the / operator and include EDivByZero as a possibility, or that some procedure accesses an array and include ERangeError.
That answer's a bit tighter than simply grepping for "raise".
Finalization sections of units can raise exceptions too. These will slip by I think... and are also somewhat problematic.
I think Delphi IDE has a build-in "stack trace" or "stack tree" something like.
This question reminds me of Skybuck's TRussianRoulette game... google it, it's code and answer may help.

Resources