仅从Boost测试框架开始。使用Ubuntu + gcc(如果重要的话,可以在Windows上通过新事物运行)。当我运行测试时,得到以下信息:
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"
我将如何查找代码中发生的位置?消息指示测试中指向一行的唯一指示。有问题的行是:
BOOST_CHECK(matches(phraseList, bitset));
我相当确定问题出在matches()
函数内部某处(可能有多个层次),但是...在哪里?
如果有人正在阅读此书,那么“重复”的答案都不起作用;显然,人们是在不考虑上下文的情况下关闭它的。
Boost测试框架用其自己的信号处理程序替换(并在执行每个测试之前执行)。这意味着在每个测试的开始,您都需要更换信号处理程序。我最终得到了这样的东西...
某些标头:
struct SignalToStacktraceScope
{
SignalToStacktraceScope();
~SignalToStacktraceScope();
};
某些源文件:
#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
,然后在每个测试功能的顶部放置一个SignalToStacktraceScope
(或包装BOOST_TEST_CASE
宏以添加它)。在测试开始时执行一次操作将无济于事,因为Boost会不断替换它。