I have some delphi code, kind of like this:
try
//some code
//occasionally throws an exception here, for example an EIndexOutOfRangeException
//more code...should get skipped if exception is thrown
finally
// there may or may not be any important cleanup code here
end;
The exception in this case is not something that needs handling beyond breaking out of the try block. So, before mad-except was added to the project for error troubleshooting, this code was "working". But now I'm getting bug reports because MadExcept is reporting the uncaught exception.
Related question, MadExcept triggers on try finally indicates the behavior of MadExcept breaking in such circumstance is "expected" because the exception isn't "handled".
I would like some clarification about what my options are as far ways to prevent a mad-except dialog from popping up when this code runs, regardless of whether there's an internal exception being thrown and ignored.
So I'm correct in thinking there's no switch to disable MadExcept from breaking on unhanded exceptions in a try/finally block? And I'm going to need to explictly "catch" the exception even if I wish to ignore it?
Should I be doing something like this (ignore any exception):
try
//some code
//sometimes throws EIndexOutOfRangeException here
//more code...should get skipped if exception is thrown
except do begin end;
end;
or perhaps (ignore a very specific exception):
try
//some code
//sometimes throws EIndexOutOfRangeException here
//more code...should get skipped if exception is thrown
except on E : EIndexOutOfRangeException do begin end;
end;
or maybe it needs to be:
try
try
//some code
//sometimes throws EIndexOutOfRangeException here
//more code...should get skipped if exception is thrown
except on E : EIndexOutOfRangeException do begin end;
finally
// some cleanup code
end;
If all three of those are valid solutions, should I prefer one over the other for any reason?
So I'm correct in thinking there's no switch to disable MadExcept from breaking on unhanded exceptions in a try/finally block?
Yes. try/finally is not exception handling; it's guaranteed cleanup, whether or not an exception occurs. As such, try/finally blocks are completely irrelevant to exception handling tools such as MadExcept.
And I'm going to need to explicitly "catch" the exception even if I wish to ignore it?
Yes. That's how exceptions work. They work their way down the stack until they find a handler that catches them. If no such handler exists, the OS interprets it as a crash and terminates the program. Delphi's TApplication object installs a handler very close to the bottom of the call stack so that your program won't crash, and MadExcept hooks this so that if an exception reaches this point, a report will be generated.
If you want to ignore an exception, yes, you do need to catch it, because what you are doing is formally "handling the exception by catching it at this point in the stack unwinding and ignoring it." That part about "catching it at this point in the stack unwinding" is important, since it means that the stack unwinding halts at that point and the program resumes normal execution. If you just ignored it, (ie. did nothing about it in your code, including not installing an exception handler,) it would continue to unwind the stack all the way to the default handler, whether or not you had MadExcept installed.
So yeah, in this case, example #2 is the correct course of action. Example #3 would be valid too, if you have cleanup code that needs to be performed at this point. But example #1 should never be done under any circumstances because it means you might end up ignoring an exception that you were not anticipating, and then you end up with corruption in your program and you never become aware of it.
It seems to me that you have a fundamental mis-understanding about what finally means.
A finally block does not influence the propagation of an exception. It just ensures that the finally block will execute, even if an exception has been raised, or the normal execution flow has been modified by exit, break etc.
Take the try/finally out and madExcept will still report that the program raised an exception that was not handled.
There are ways to tell madExcept to ignore certain exceptions. For instance some exceptions should be silent. The canonical example of such is EAbort. You would use RegisterExceptionHandler to customise how unhandled exceptions are treated. Although, as I will explain, I doubt this to be the solution for your problem.
What you need to do next is forget about madExcept. You need to work out what to do about this exception. Do you want to handle it here, or do you need to let the exception propagate? Only you can really know that. But madExcept is not the driver here. What must drive your decision is the correct execution of your program. Should the exception be handled or not, to make your program behave correctly? You must get that right first, and then worry about madExcept.
If you need to handle it here, then handle it selectively. Don't catch all exceptions. That's an absolute no-no. But if you handle it here, ask yourself if that is sensible. The code failed to perform some action. Is there some subsequent code that relies on that action succeeding? By handling the error, and ignoring it as you propose, you are forcing all subsequent code to be ambivalent about the success or failure of this action. That seems highly dubious to me.
Now, the exception is EIndexOutOfRangeException. That means you wrote something like A[i] where the value of i is invalid. I cannot think of a scenario where that would be acceptable. So it looks to me that your program contains an error and is simply using an invalid index. You should fix that error properly by not accessing out of bounds. Don't suppress the exception, stop it being raised.
Another way to look at this. How can you tell the difference between your current situation, and that which would arise from writing A[-i] instead of A[i]? Suppressing the exception means that you cannot detect such egregious errors as this.
The bottom line, so far as I can tell, is that madExcept is reporting an error in your code. You should regard madExcept as your friend and listen to what it says. It is telling you that you have a defect in your code that should be fixed.
Related
I am new to ARMv8 architecture and while reading the v8 exception vectors I am not able to understand significance of adding SP_EL0 level vectors while SP_ELx vector set exists. What I am trying to find a use case where this is useful. I understand that when the exception is taken at same level by default the stack of same exception level is used for example if EL2 (Hyp) mode is defined then if exception occurs while being at EL2 level the stack defined at EL2 will be used but not sure if I configure to use EL0 level stack under what use cases this could be useful ? Can some one give a use case and explain ?
Also while going through the spec it seems these two different stack usage idea is taken from Cortex-M architecture but i am not very clear with thread and handler modes as well. Can any one explain it ?
Just wanted to add here that ARMv7 doesn't have thread and handler concept so i am not clear requirement in ARMv8.
Thanks
SP_EL0 is the "normal" stack pointer. Your code that runs in any EL should be running on SP_EL0 whenever it can. SP_EL1/2/3 is the "exception" stack pointer for that mode. When an exception, fault, or interrupt happens, the processor switches to this stack (and possibly switches EL). Your exception handler code should do what it needs to save the exception state and get itself onto SP_EL0 to complete handling the exception.
That is, your EL0 user code, your EL1 kernel code, your EL2 hypervisor, and your EL3 monitor should all be using SP_EL0 except in the early stages of their exception handlers. If you were to take a nested exception while on SP_ELx (non-zero), you could blow over your stack, ELR, FAR, etc. which is why you want to save these and get back to SP_EL0 as soon as you can.
Using Delphi and FastReport I get this error message while debugging inside Delphi immediately after this line:
<FastReport_Component>.ShowReport(true);
Then this error appear:
Project myapp.exe raised exception class EVariantTypeCastError with message 'Could not convert variant of type
(String) into type (Double)'.
It appears twice before displaying the report. but if I run myapp without debugging no error message appear.
How I can find which memo cause this error ? the report has so many memos. some has also expressions inside using IIF and the error message does not display any more info.
This is just the debugger. It's probably just getting an expected error (one handled by a try..except in the FR code) and properly dealing with it, but the debugger has no way of knowing that and tells you the exception happened. (It's a common issue when working with Indy, which raises exceptions as part of normal program flow.)
There are three ways to deal with this situation when debugging:
Just hit Continue on the exception dialog when it appears. (You can tell it's a debugger exception because you get the Break or Continue option, and because it only happens when debugging.)
You can disable a specific exception class (or all exceptions) when debugging, using the Tools->Options->Debugger Options. In this case, you can add EVariantTypeCastError to the list of exceptions to ignore.
(My preferred method) Use the Advanced Breakpoint Properties dialog to skip the debugger's exception handling around the specific line of code you know will raise the exception you want to ignore.
Set a breakpoint on the line immediately before the problem code line.
Right-click the breakpoint on the line before, and choose Breakpoint Properties from the context menu.
Click the Advanced button on the Breakpoint Properties dialog, and in the Actions groupbox, uncheck Break and check Ignore subsequent exceptions.
Repeat the previous steps on the line after the problem code, except check Break and uncheck Ignore subsequent exceptions on this second breakpoint.
Run your code as usual. The debugger will skip it's exception handling on the code between the two breakpoints.
The advantage of option #3 is that it ignores all exception handling, but only on the code block between the two breakpoints, so you still get exceptions in all other areas of your code that may be valid exceptions in the debugger.
I got this exact same error but not with FastReport. I'll leave the context of my error, as it may help someone else. I got this error on:
RESTRequest.Execute();
I was using the TClientDataSet with TRESTResponseDataSetAdapter so that after a request to my web service the adapter would load a data set with the JSON string returned by the web service. This data set was being used to automatically check/uncheck checkboxes and load textedits and comboboxes. Since TJSONObject does not parse booleans correctly in json, I changed some checkboxes to check/uncheck based on an integer value instead of a boolean. I was then changing my webservice so that it looks for boolean columns in the datatable to an integer value 1 or 0. For some reason (my fault entirely), I was outputting a json with "" in that field instead of the integer ("1" or "0"). And this yielded that exact error. After correcting this, the error disappeared.
I had a similar issue in FastReport. In my case, it was a wrong Format applied to a MemoView. I could find the name of the offending component this way:
Use Break to stop the execution
In the Call Stack panel, find the latest call from a fastreport class (in my case: frxClass.TfrxCustomMemoView.FormatData(...) and double click it.
if you don't have the source code od Fast Report, a dialog appears - just hit Cancel
in Local Variables panel, you will probably see name of the offending component / value / format.
Some part of my source code are nested inside try statements in order to handle some run time errors, at the same time each and every line must be tried to execute even if the previous line is not executed because of run time error .
currently my code looks like this
try
try
//statement1
except
end;
try
//statement2
except
end;
try
//statement3
except
end;
finally
//something
end;
I am very sure going in the wrong way ,even if the final out put is working well, I have to do this for dozens of lines.
Is there any better way to implement this
If you want each statement to execute then you have to write it the way you have done. Note that in that case may not need the try/finally because you are swallowing all the exceptions.
However, the code does look a bit odd to me. I wonder if you really need each and every statement to execute. Normally you would write:
try
statement1;
statement2;
statement3;
except
//handle exceptions
end;
Then, if there is an exception in statement1, the other two lines will not execute.
However, it would be even more common not to handle exceptions at all and let them float up to some higher level handler. If you are making routine logic decisions using exceptions then that would be considered bad practice.
I think it would be helpful for you to publish some of your code that handles the exceptions and some details of what exceptions you are expecting to occur. Then we could give you some more specific advice.
When an unhandled exception happens while debugging some code in any procedure/function/method, the debugger stops there and shows the message.
If I now continue debugging step by step, the execution jumps directly from the line that created the exception to the end of the current procedure (if there is no finally block).
Woulnd't it be just as good to continue with the next line of the current procedure?
Why jump to the end of the proc and continue with the calling procedure?
Is this just by design or is there a good reason for it?
An exception is a unexpected situation, that why processings is stopped.
The jump to the end of the procedure is an invisible finally statement to release any locally "allocated" memory, like strings, interfaces, records etc.
If you want to handle a exception the you have to incapsulate the call that can give an exception with try .. except statement, and use an "on" clause to only handle that particular exception that you want to handle.
In the except you can inspect variables in the debugger and in code you can raise the exception again if needed.
In general, an uncaught exception will execute a hidden "finally" in each function on the stack, as it "unwinds" up to an exception handler. This cleans up local variables in each stackframe. In languages like C++ with the Resource Acquisition Is Initialization paradigm, it will also cause destructors to run.
Eventually, somewhere up the callstack, the exception will be caught by a handler. If there's no explicit one, the system-provided one will kill the process, because what else can it reasonably do?
Throwing an exception is a way of saying "Something unexpected happening. I don't know how to handle this". In such case it it better not to do anything (other than throwing the exception) than to try to continue, not knowing if what you're doing is correct.
In real life you have the same kind of thing: If someone asks you to count to 10 in Hebrew (or some language you don't know), you just say you don't know. You don't go ahead and try anyway.
I would expect it to jump to the end of the proc, and then jump to the except or finally block of the calling proc. Does it really continue in the calling proc as if nothing had happened? What does it use as the return value (if it's a function call)?
Continuing with the next line in the original proc/function would be a very bad thing - it would mean the code executing radically differently in a debugger to in release (where the exception would indeed cause execution to exit that proc/function unless there's an except/finally block). Why should debugging let you ignore exceptions completely?
It has to unwind the stack to find a handler.
I do agree it's very annoying behavior. Continuing isn't an option but it sure would make life easier if the debugger was pointing to the spot that threw it with the local variables still intact. Obviously, the next step would be to the hidden finally, not to the next line.
I just want to be able to examine everything I can about what caused it. I was just fighting this not very long ago. Text parsing, I KNEW the offending string contained no non-numeric characters (sanity limits mean the overflow case should never happen, it's my data file, all I'm worried about is oopses) and so I didn't put an exception handler around the StrToInt--what's this nonsense about it not being a valid number????? Yup--the routine wouldn't call it with anything non-numeric in the buffer--but an empty string has nothing non-numeric in it!
In one of our application im getting an exception that i can not seem to find or trap.
...
Application.CreateForm(TFrmMain, FrmMain);
outputdebugstring(pansichar('Application Run')); //this is printed
Application.Run;
outputdebugstring(pansichar('Application Run After')); //this is printed
end.
<--- The Exception seems to be here
The Event log shows
> ODS: Application Run
> //Various Application Messages
> ODS: Application Run After
> First Change Exception at $xxxxxxxx. ...etc
All i can think of is it is the finalization code of one of the units.
(Delphi 7)
Try installing MadExcept - it should catch the exception and give you a stack-trace.
It helped me when I had a similar issue.
Here's two things you can try:
1) Quick and easy is to to hit 'F7' on the final 'end.'. This will step you into the other finalization blocks.
2) Try overriding the Application.OnException Event.
The SysUtils unit actually sets up the default ErrorProc and ExceptProc procedures in its initialization section, and undoes them in its finalization section, so often in this situation it's worth ensuring that SysUtils is the very first unit in the uses clause in your dpr, so then it will be the last one finalised. Might be enough to get you some meaningful data about what is going wrong.
Finalization exceptions are tricky. Even if you put SysUtls first in your project file, your application object may already be gone, which means your global exception handler is gone too. MadExcept may work for this though.
Another solution is to put a Try / Except block in each of your unit finalization sections, and then handle the exceptions there.
What is your objective? Do you want to suppress the exception or debug it? Debugging it can be done by stepping through them with F7 as Zartog suggested. If you discover which unit has the exception in finalization then you might try placing it in a different order in the uses clause it is called from.
Good luck!