Just starting out with boost test framework. Using Ubuntu + gcc (running on Windows through the new thing if that matters). When I run my tests, I get this:
unknown location(0): fatal error: in "PhraseListTest/everythingEqual8": signal: SIGSEGV, si_code: 0 (memory access violation at address: 0x00000080)
/mnt/c/projects/matching/matching-native/src/test/cpp/phrase_list_test.cpp(70): last checkpoint
*** 1 failure is detected in the test module "burningmime_matching_tests"
How would I go about finding where in my code that happened? The only indication that message gives points to a line in the test. The line in question is just:
BOOST_CHECK(matches(phraseList, bitset));
I'm fairly certain the problem is occurring somewhere inside the matches()
function (probably many levels deep), but... where?
In case anyone is reading this, none of the "duplicate" answers work; obviously people closed it without considering the context.
Boost Test Framework replaces the signal handlers with its own (and does it before executing each test). That means at the beginning of each of your tests you need to replace the signal handler. I ended up with something like this...
Some header:
struct SignalToStacktraceScope
{
SignalToStacktraceScope();
~SignalToStacktraceScope();
};
Some source file:
#include <cstdio>
#include <csignal>
#include <iostream>
#include <boost/stacktrace.hpp>
#if !NDEBUG && !BOOST_OS_WINDOWS
typedef void (*FSignalHandler)(int signum);
static void stacktraceHandler(int signum, const char* signame, FSignalHandler oldHandler)
{
fprintf(stderr, "\n\n===========================================\nReceived signal %s\n", signame);
fflush(stderr); // flush before stack trace in case getting the stack trace itself produces another segfault
std::cerr << boost::stacktrace::stacktrace();
fprintf(stderr, "===========================================\n\n");
fflush(stderr);
// then raise the signal again to go back to the test framework
signal(signum, oldHandler);
raise(signum);
}
#define FOREACH_SIGNAL(F) \
F(SIGSEGV) \
F(SIGFPE) \
F(SIGABRT) \
F(SIGTERM)
#define DEFINE_SIGNAL_WRAPPER(S) \
static FSignalHandler oldHandler_##S = nullptr; \
static void stacktraceHandler_##S(int signum) \
{ \
stacktraceHandler(signum, #S, oldHandler_##S); \
}
FOREACH_SIGNAL(DEFINE_SIGNAL_WRAPPER)
#undef DEFINE_SIGNAL_WRAPPER
SignalToStacktraceScope::SignalToStacktraceScope()
{
#define HOOK_SIGNAL_WRAPPER(S) oldHandler_##S = signal(S, &stacktraceHandler_##S);
FOREACH_SIGNAL(HOOK_SIGNAL_WRAPPER)
#undef HOOK_SIGNAL_WRAPPER
}
SignalToStacktraceScope::~SignalToStacktraceScope()
{
#define UNHOOK_SIGNAL_WRAPPER(S) { signal(S, oldHandler_##S); oldHandler_##S = nullptr; }
FOREACH_SIGNAL(UNHOOK_SIGNAL_WRAPPER)
#undef UNHOOK_SIGNAL_WRAPPER
}
#undef FOREACH_SIGNAL
#else
SignalToStacktraceScope::SignalToStacktraceScope() { }
SignalToStacktraceScope::~SignalToStacktraceScope() { }
#endif
And then put a SignalToStacktraceScope
at the top of each test funciton (or wrap the BOOST_TEST_CASE
macro to add that). Doing it once at the beginning of the tests won't help, since Boost will keep replacing it.
User contributions licensed under CC BY-SA 3.0