Given the basic code:
std::vector<int> foo(10);
foo.at[100] = 42;
This will throw an std::out_of_range as expected, and the default behaviour on my machine is to print a string like:
terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 100) >= this->size() (which is 10)
If I wrap the code with a try/catch:
try {
foo.at[100] = 42;
} catch (std::out_of_range e) {
printf("Error at %s line %d\n", __FILE__, __LINE);
}
I can of course get the line where the problem occurs, but if the code has tens of uses of at and I do this:
try {
functionThatCallsAtFromLotsOfPlaces();
} catch (std::out_of_range e) {
printf("Error at %s line %d\n", __FILE__, __LINE);
}
I only get the line number of the catch, not the throw.
On the other hand, if I load up the program in gdb and type catch throw, gdb will hand control back to me at the throw, so I can easily trace where exactly the error is, not where it was caught. Is there a mechanism in C++11, or gcc-specific, where I can emulate what gdb is doing?
Note, there is this question, but that is for signal errors; it doesn't work for me for normal throws.
boost::exception e.g. stores the stack trace on an initial throw. std:: exception doesn't and hence you can't see the stack trace before it was unrolled. Rethrowing the original exception nested in something like a Boost exception would provide you a stacktrace, but still only up to the creation of the nested exception.
There is no way around that, all you could do, is installing a custom handler to catch exceptions as they are thrown, but that is very much compiler and runtime specific. Essentially you would use the ports which area designed for debugging.
Anyway, you should really not care about stack traces for an exception you have caught. It's better to just let the exception crash in such case, and utilize full crash dump creation with Breakpad or alike, for posthum analysis with not only full stack trace, but also stack contents intact. Only catch exceptions from which you intend to recover, everything else is just error concealing (even if not intended) and makes debugging harder.
Related
The Windows API CopyFile function is rather straightforward:
BOOL CopyFileW(
[in] LPCWSTR lpExistingFileName,
[in] LPCWSTR lpNewFileName,
[in] BOOL bFailIfExists
);
...
If the function fails, the return value is zero. To get extended error
information, call GetLastError.
However, I found this gem in our C++ source code, dating back to Oct / 2006:
try { //Exception, if the file already exists and is write protected
bCopyOK = CopyFile(csSourceFile, csDestinationFile, bFailIfExists);
} catch (...) {
bCopyOK = FALSE;
}
I even found the old ticket title (of course without details): "function 'CopyFile' throws Exception if Destination is write protected, catch Exception" :-)
Even today we still compile with /EHa, so this would have caught any SEH exceptions raised.
Now, at this point in time we would've been using Visual Studio 6 on Windows XP, and that one had all kinds of quirks, but still: I have a hard time imagining this function ever raising an exception (apart from invalid/null parameters and such).
Does or DID Win32 CopyFile(W) ever raise a (SEH) exception?
NO.
at first not exist SEH exceptions at all. SEH this is type of exception handler but not type of exception. another type of handlers (not exceptions) is VEH.
exception can be raised or via invoke RaiseException /RtlRaiseException / ZwRaiseException or by CPU. of course CPU exception alwas can be raised (in case lpExistingFileName or lpNewFileName for instanse point to invalid memory ) but CopyFileW never call RaiseException - by fact and by documentation.
//Exception, if the file already exists and is write protected
so in what problem ? create write protected file lpNewFileName and call CopyFile and test result. will be exception or error code returned
// Self answer, with historical perspective.
It is not documented to throw exceptions, as is apparent from the current docs linked above.
Both the other answer and also, e.g. Do DeleteFile() Or CopyFile() throw exceptions? quite definitely assert that there should be no exception being raised.
However, as is mentioned in comments:
Very few API calls are documented to raise SEH exceptions, but that
doesn't mean that they won't, or prevent SEH exceptions raised in
foreign code from passing through.
and in the linked question:
comment: ... Some odds that getting rid of the installed anti-malware product can rescue it, ymmv. ...
A: It was ... corporate info safety system, anti-malware like product.
It is very well possible that the original developer could actually reproduce this behavior on his machine, and swallowing the error "fixed" it well enough back then.
Things have improved since then. Given that no reproduction is possible in current code, and given that this only works with /EHa anyways, the try-catch is a candidate for cleanup.
I'm curious how Windows handles exceptions. More exactly, how Windows find the catch block of a try / catch. I saw that the compiler makes a separate function in assembly for catch block. Since the catch block was represented by another function in assembly, I couldn't find any correlation between the instruction that was generating the exception and the RUNTIME_FUNCTION entries from .pdata section.
I tried to put a breakpoint on RaiseException, RtlRaiseException and RtlVirtualUnwind but all I could find was the address after the RaiseException call. Tried to debug a divide by 0 exception, but it looks like the debugger has some additional exception handlers and the message in the catch block was not printed.
Any additional information about Stack Unwinding on Windows 64bit are welcome :D.
The exceptions are handled by exception handler routines.
When you add a try/catch block to your C++ code you will see that the compiler added __CxxFrameHandler3 to your import table (providing that the MSVCRT is not statically linked). So this is your exception handler that will be called when an exception occurs in the try block.
Another one __C_specific_handler is imported when you add __try/__except block to your C or C++ code.
There are a few others but these two are used in the C/C++ code.
To answer your question, the best way is to hook (replace the import table pointer with a pointer to your local routine) one of these functions and see how your "handler" will be called when an exception is thrown.
With the goal of finding C++ catch you can set Vectored Exception Handler and set a breakpoint in it. VEH goes before frame-based handlers, so it it not too late:
LONG NTAPI vh(EXCEPTION_POINTERS* ExceptionInfo)
{
return EXCEPTION_CONTINUE_SEARCH;
}
AddVectoredExceptionHandler(TRUE, vh);
Alternatively, if you want to set breakpoint closer to catch block, have __try...__except deeper in call stack than target catch block, in __except expression return EXCEPTION_CONTINUE_SEARCH and have your breakpoint there.
In Matlab, there is, as far as I know, no good way to conditionally catch exceptions (correct me if I'm wrong). The only way is to catch the exception, check the identifier, and rethrow the error if this particular error can not be handled. That's acceptable though inconvenient. However, when I use Matlabs dbstop if error, I end up at the ME.rethrow() line. I'm then unable to dbup back to the place where the original error was caused.
function test_excc
try
sub_test()
catch ME
if strcmp(ME.identifier, 'test:notsobad')
fprintf(1, 'Fine\n');
else
ME.rethrow();
end
end
end
function sub_test
sub_sub_test();
end
function sub_sub_test()
if rand>0.5
error('test:error', 'Noooo!');
else
error('test:notsobad', 'That''OK');
end
end
Example usage:
>> test_excc()
Error using test_excc>sub_sub_test (line 21)
Noooo!
Error in test_excc>sub_test (line 16)
sub_sub_test();
Error in test_excc (line 4)
sub_test()
9 ME.rethrow();
K>> dbstack
> In test_excc at 9
Although the Matlab desktop environment prints the entire stack trace back to sub_sub_test, the debugger does not give me the possibility to go up the stack trace and debug inside this function.
I am aware of dbstop if caught error. However, this will debug into any caught error, which may be many if software makes heavy use of exceptions. I only want to stop on uncaught errors, but I want to stop where the error is generated — not where it's rethrown.
My question:
In Matlab, how do I conditionally catch an error (based on error identifier) and debug into the place where the error is originally thrown?
I would guess that you cannot do this. As soon as execution enters the catch statement, dbstack will have to refer to that location inside the catch, so the information necessary to debug at the cause of the error is lost. ME.stack will tell you where the exception came from, but that isn't sufficient to debug at that location.
So I doubt you can solve the problem by doing something clever inside the catch. Looking at the documentation for catch, there also doesn't seem to be a way to do a java-style catch (ExceptionType ME).
There might be some hacky ways to solve this by using debug commands programmatically. For example, S = dbstatus saves the debug state and if there was a way to resume from a saved state, then you could attach this to the exception. But I can't find any documented way to do that.
I'm protecting my own C++ code (Windows x86) from exceptions in a third party COM object and logging those exceptions using the following SEH pseudocode.
__try {
hr = m_ComObj->SomeFunc();
} __except ( LogExceptionInfo(GetExceptionCode(), GetExceptionInformation()) ) {
hr = E_UNEXPECTED;
m_ComObjCrashed = true;
}
Is this approach likely to catch exceptions that would be handled if the SEH code wasn't present?
An MSDN article below mentions that the default unhandled exception filter will catch and fix the case where code writes to memory in loaded resources. Are there other cases where using SEH will interfere with desirable default OS behaviour?
A Crash Course on the Depths of Win32™ Structured Exception Handling
Yes it's quite reasonable.
It will catch all exceptions that are unhandled in the COM function
I don't see any interference-related problems with default OS behaviour
An MFC, C++ application I'm working on seems to be throwing an exception deep inside a device driver. (It's an access violation writing to a NULL pointer from the looks of things. The details of the crash are not what is interesting me right now, however...)
I can get the Visual Studio Debugger to break when the exception occurs through the Exceptions dialog. What I would like to know though is where the exception is being caught. Visual Studio can pass the exception on to the program being debugged, but there doesn't seem to be anyway (that I know of) to single step to the next instruction so I can view the callstack from the exception handler's point of view.
Does anyone know whether it is possible to step to the exception handler that will catch the exception or not?
Cheers,
James
With WinDbg, you can use the !exchain command. With !exchain -c, it will show your C++ destructors and catch blocks. e.g.
Try block 0
Catch block 0, type: module!my_exception `RTTI Type Descriptor'+0 (6071409c)
handler: module!catch_block+582 (6063bcc2)
Then you can set a breakpoint with bp 6063bcc2.
I don't know of a way to do this in Visual Studio.
At the point when the exception is being thrown you should have a call stack available to you in the debugger -- by looking at each stack frame from the point of the throw to main, you should be able to find the first frame with a try/catch block wrapping the call to the next routine in the frame. As long as that try/catch block handles the type of exception being thrown, that's where it'll land.