If an exception is thrown in a C++ program control is either transferred to the exception handler or terminate()
is called.
Even if the program emits some diagnostics from inside the handler (or from terminate()
handler) that can be too late - the most value is in the call stack at the point where the exception is thrown, not in the handler.
On Windows a call stack can be obtained开发者_运维百科 using [StackWalk64()
]1 function. The key is how to call that function at the right moment.
Is there a way to make a Visual C++ program execute some user code each time an exception (or an exception for which no handler is set) is thrown?
If you want to do stuff when an SEH exception is thrown, such as when an access violation occurs, then you can simply catch the SEH exception (either with a __finally, or with a conversion to a C++ exception (see here)) and access the context within the exception which is the context at the time the exception was thrown. You can then generate either a callstack using StackWalker or a mini dump. IMHO it's better to produce a mini dump.
If you want to catch C++ exceptions at the point they're thrown and you don't have access to the source to the C++ exception classes then you need to get a bit craftier. I deal with this problem by running the target process under a custom debugger - use the Debug API (see here) which gets notifications of when an exception is thrown. At that point you can create a mini dump or call stack of the target process.
On Windows I'm using SetUnhandledExceptionFilter and MiniDumpWriteDump to produce a minidump.
__try, __except are very helpful.
Is there a way to make a Visual C++ program execute some user code each time an exception (or an exception for which no handler is set) is thrown?
Put that code into the constructor of your exception base class.
When the language doesn't support it, and you can't live without it, hack... :-/
#include <iostream>
#include <stdexcept>
namespace Throw_From
{
struct Line
{
Line& set(int x) { x_ = x; return *this; }
int x_;
template <typename T>
void operator=(const T& t) const
{
throw t;
}
};
Line line;
}
#define throw Throw_From::line.set(__LINE__) =
void fn2()
{
throw std::runtime_error("abc");
}
void fn1()
{
fn2();
}
int main()
{
try
{
fn1();
}
catch (const std::runtime_error& x)
{
std::cout << Throw_From::line.x_ << '\n';
}
}
This is a great article on how to catch all different types of exceptions in Visual C++.
It also provides you with a crash dump that comes useful for debugging.
精彩评论