Print stack traces on SEH exceptions on Windows
Also tidies up a couple of things:
- Prevent handling of stack overflows, which cannot be done safely
- `exception_code` is a macro, so we rename it
- The `std::string` heap allocation was unnecessary
Fixes #4298
PiperOrigin-RevId: 544117790
Change-Id: I8ba61f87119d5fbdb1f653700d9867ca6f8c28ce
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index d1eddf1..704e1ac 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -866,7 +866,7 @@
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
-int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) {
// Google Test should handle a SEH exception if:
// 1. the user wants it to, AND
// 2. this is not a breakpoint exception, AND
@@ -881,9 +881,11 @@
if (!GTEST_FLAG_GET(catch_exceptions))
should_handle = false;
- else if (exception_code == EXCEPTION_BREAKPOINT)
+ else if (seh_code == EXCEPTION_BREAKPOINT)
should_handle = false;
- else if (exception_code == kCxxExceptionCode)
+ else if (seh_code == EXCEPTION_STACK_OVERFLOW)
+ should_handle = false;
+ else if (seh_code == kCxxExceptionCode)
should_handle = false;
return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
@@ -2555,17 +2557,12 @@
#if GTEST_HAS_SEH
-// Adds an "exception thrown" fatal failure to the current test. This
-// function returns its result via an output parameter pointer because VC++
-// prohibits creation of objects with destructors on stack in functions
-// using __try (see error C2712).
-static std::string* FormatSehExceptionMessage(DWORD exception_code,
- const char* location) {
+static std::string FormatSehExceptionMessage(DWORD exception_code,
+ const char* location) {
Message message;
message << "SEH exception with code 0x" << std::setbase(16) << exception_code
<< std::setbase(10) << " thrown in " << location << ".";
-
- return new std::string(message.GetString());
+ return message.GetString();
}
#endif // GTEST_HAS_SEH
@@ -2613,14 +2610,20 @@
return (object->*method)();
} __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
GetExceptionCode())) {
- // We create the exception message on the heap because VC++ prohibits
- // creation of objects with destructors on stack in functions using __try
+ // We wrap an inner function because VC++ prohibits direct creation of
+ // objects with destructors on stack in functions using __try
// (see error C2712).
- std::string* exception_message =
- FormatSehExceptionMessage(GetExceptionCode(), location);
- internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
- *exception_message);
- delete exception_message;
+ struct Wrapper {
+ static void ReportFailure(DWORD code, const char* location) {
+ return internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatSehExceptionMessage(code, location) +
+ "\n"
+ "Stack trace:\n" +
+ ::testing::internal::GetCurrentOsStackTraceExceptTop(1));
+ }
+ };
+ Wrapper::ReportFailure(GetExceptionCode(), location);
return static_cast<Result>(0);
}
#else