I have GDB attached to a process that is currently inside a catch(...) block.
Is there a known technique to access that thrown exception?
The program in question is a gcc/x86-64 binary, but I'm also curious about other builds.
As you say, you can re-throw it, so you can re-throw it inside another try/catch block with more specific clauses to extract the exception (and another ... if you want as well). You can even do this inside another function so you can centralize your exception handling.
Edit: I misunderstood the importance of gdb in your question, but you can apply the idea I described. Make a function that re-throws the exception you can set a breakpoint in:
void
helper()
{
try {
throw;
} catch (int i) {
// anything that won't get optimized away
volatile int j = i; // breakpoint here
}
}
Then in gdb just do call helper(). I just tested this to be sure it worked.
Further edit: If you literally mean I'm running a program under gdb right now and you are not exiting gdb until you are sure you can't get the exception, then it's time to look at eh_throw.cc and friends in the gcc source. __cxa_rethrow starts with:
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
You will have to examine all of those structures to figure out what's buried inside.
I have not tested this - but the exception (or at least a pointer to it) should probably be on the stack somewhere close to the head. I guess the exact position and format is implementation dependent, but you should be able casting different addresses in this area of the stack to your exception type (or at least to std::exception) and see if you get meaningful results.
Related
I'm having problems with locating the address from which a error occurred, my whole code is running inside of a "try" statement and sadly whenever something is wrong I need to find the error using the old try and fail method by deleting parts of my code. Is there a better way to do it?
My current code:
try
{
do
{
if (somefunction)
if (somefunction2)
if (somefunction3)
if (somefunction4)
}
while (false);
}
catch (...)
{
// todo: somehow get the address where the error occurred
Logger::Log("Exception\n");
}
A simple solution to find out where an exception comes from is to use a unique message within each function. Catch the exception object and print the message. Or perhaps use even a different type of exception which will allow you to efficiently handle each case differently if that's what you want to do.
As for getting an "address", the trace of function calls that lead to the current point of execution is called a stacktrace (or backtrace). The stacktrace would contain information such as addresses. Theres no standard way to get a stacktrace yet, although it has been proposed for C++23.
However, once you've caught the exception, the stack will have been "unwound" such that you can't know where the exception came from. What you could do, is get the stack trace in the code that may be throwing (each of them since you don't know which one is the thrower) and store the trace in the exception. A central place to do that would be within the constructor of a custom exception type. This pattern is common in standard exception handling of modern languages.
Lastly, you don't necessarily need to make any changes to the program, if you instead run the program in a debugger and break on a throw, you can get all the information you can possibly get.
I have a application with many classes. This application is started on the main with a sinle line, let's say something like this:
int main()
{
try
{
classA.start();
}
catch(...)
{
std::cout<<"EXCEPTION CAUGHT"<<std::endl;
}
}
After classA.start() is called, then other classes and other procedures are called. If there's any unexpected exception ocurring on those classes, the try-catch, as stated in the code above, wont catch them. I was trying and seems that I need to set try-catch on every place I think it can be a exception. My point here is, since I already cover most of the exception, I want to add this global try-catch to handle those I forgot and be able to log it and keep working.
I hope I explained myself properly.
Thanks
Yes this will indeed catch every exception thrown within your program (when main is in the call stack), but that doesn't necessarily include any undefined behaviour, for example
out of bounds array access.
invalid pointer dereference.
stack overflows.
an integer division by zero.
To repeat, exceptions thrown when objects with static storage duration are destructed, or global objects constructed or destructed will not be caught at your catch site either.
Is there any way to convert a NULL pointer access into a C++ exception under Linux ? Something similar to the NullPointerException in Java. I hope the following program would return successfully, instead of crash (assume the compiler cannot figure out this NULL pointer access during compile time):
class NullPointerException {};
void accessNullPointer(char* ptr) {
*ptr = 0;
}
int main() {
try {
accessNullPointer(0);
} catch (NullPointerException&) {
return 1;
}
return 0;
}
I'm not expecting any standard way of doing it, since NULL pointer access under C++ is undefined-behavior, just want to know how to get it done under x86_64 Linux/GCC.
I did some very primitive research in this, it might be possible:
When a NULL pointer is access under Linux, a SIGSEGV will be generated.
Inside the SIGSEGV handler, the program's memory and register information will be available (if sigaction() is used to register the signal handler). The instruction which caused the SIGSEGV is also available if the program is disassembled.
Modify the program's memory and/or register, and create/fake an exception instance (maybe by invoking the low level unwind library functions, like _Unwind_RaiseException, etc.)
Finally return from the signal handler, hope the program would start a C++ stack unwinding process like a normal exception was thrown.
Here's a quote from GCC's man page (-fnon-call-exceptions):
Generate code that allows trapping instructions to throw exceptions. Note that this requires platform-specific runtime support that does not exist everywhere. Moreover, it only allows trapping instructions to throw exceptions, i.e. memory references or floating point instructions. It does not allow exceptions to be
thrown from arbitrary signal handlers such as "SIGALRM".
It seems this "platform-specific runtime" is exactly what I want. Anyone knows such a runtime for Linux/x86_64 ? Or give me some information on how to implement such a runtime if no such runtime already exists ?
I want the solution to work in multi-threaded program as well.
No, there's no good way to do that, and there shouldn't be. Exceptions are thrown by a throw statement in source code. That's important for reasoning about exception safety: you can look at the code and see the places where exceptions can be thrown and, perhaps more important, you can look a the code and see the places where exceptions will not be thrown. If pretty much anything you do can throw an exception it becomes very difficult to write exception-safe code without cluttering it with catch clauses. Microsoft tried this in their early C++ compilers: they piggybacked C++ exception handling on top of their OS's structured exceptions, and the result was a disaster.
Register an alternative signal stack with signalaltstack().
The 3rd argument to a signal handler handler registered with the SA_SIGINFO is a pointer to a ucontext_t which contains the saved register. The signal handler should adjust this to simulate a call to a function. That function can then throw the exception.
Potential complications include the need to preserve the value of callee saved registers, the red-zone on x86-64 (which can be disabled) and the return address register on some ISAs, such as ARM.
I have the following code for extracting a string out of a buffer array.
It works fine. However, the length variable is determined at runtime, so if it were to go out of bound, an exception would occur. Of course, the code can be easily adjusted to check if the length variable (in relation to the offset variable) falls within the boundaries. Though I'm curious why the following code does not work, as the exception seems to fly through the try-catch statement (and get caught by the debugger).
try
{
string value(&buffer[offset], length);
// ...
}
catch (exception& e)
{
// ...
}
catch (...)
{
// ...
}
Running on Windows 7 64bit, MSVCR compiled.
Accessing the buffer array beyond bounds is undefined behaviour. There is no requirement for a C++ exception to be thrown in this case. Try instantiating the string outside a try block and you'll see for sure whether an exception is thrown.
I think the term "exception" is confusing you. When we talk about an exception that catch can catch, we don't mean "exception" in the general computer science sense. We mean specifically a C++ exception that is thrown with the throw operation.
You have no code that throws an exception, why would you expect to catch one? If you want to throw an exception in this case, you have to write code to do it.
Sometimes I see programmers expecting to be able to catch, for example, a division by zero. While that's an exception in the general computer science sense, it's not a C++ exception unless you have some code that creates a C++ exception when there's a division by zero and throws it.
Your program might be causing a fault due to accessing a memory location that the system knows is not valid for your process, for example dereferencing a NULL pointer (always faults) or going outside the bounds of a variable in the heap (not always faults, depends on page boundaries). These faults are detected by the CPU, and are a different mechanism than the exceptions that you can catch with try/catch in C++, those are part of the language and implemented by the compiler and language runtime library.
In your case since you are using MSVC you have access to an extension to the language that allows you to catch both, the __try and __except facility, you can read more about the MSVC try-except Statement here.
This is the code:
#include <iostream>
void f() {
throw 1;
std::cout << "f(): should not be printed!!\n";
std::cout << "f(): not should this!!\n";
}
int main(int, const char**) {
f();
std::cout << "main(): This not be printed!!\n";
return 0;
}
When run as a console application, in debug mode and under the debugger there is no stack unwinding and the cout statements get printed?
This is technically possible if you run with the debugger. You didn't tell the whole story though. The debugger will display a dialog first when the exception is thrown. It looks similar to this (mine is VS2012 on Windows 8):
If you click the Break button then the debugger will break at the throw statement, giving you a chance to inspect state. When you click the Continue button then the exception is ignored and the program will continue as though nothing happened. This also happens when you break and then resume running.
This is a feature, not a bug, it allows you to rescue a debug session on which you already spent a lot of time. It is of course not often that useful to continue since your program is likely to be in a bad state but the alternative isn't great either. You almost always want to favor clicking Break and use the debugger to correct state so that you can meaningfully continue debugging.
Of course this will never happen without a debugger, your program will instantly terminate.
The only possible way that a stack unwind is ever going to happen is by writing a catch clause that catches the exception. Regardless of whether you are debugging or not.
The key in answering my own question lies in answering another sub-question: right after an exception is thrown, at which point does the stack unwinding begin? By stack unwinding is meant the call, in reverse order, of destructors of all automatic objects that still exist. Answer: at the point the control is passed to the exception handler, i.e. the exception is caught. If the exception is not caught, the C++ exception mechanism dictates that the terminate function is to be called and this in effect by default calls abort(). This mechanism can be seen in action by the following code:
struct X {
~X() { std::cout << "~X !!\n"; }
};
int main(int, const char**) {
X x;
throw 1;
return 0;
}
After the throw, the destructor for X is never called because the no exception handler has gained control and so the program aborts.
Back to the initial question, in the situation of when you are debugging a debug build and during execution of the program an exception is thrown when there is no suitable try-catch block around it, the MS Studio debugger breaks at the throw point and presents you with the dialogue window shown above and provides you with the option to “continue”. Continue is to be interpreted not as “carry on with the exception mechanism” but as “carry as if nothing has happened” i.e. with the next line of code after the throw.