Is there a way to make GDB stop at named symbols when they reach the top of the stack? I ask because after the stack frame shown in the picture below, the program seems to execute several functions (too many to step through) without symbol information, just addresses, and then crash the executable. If there is any way to automatically stop when the top of stack pushes or pops to any function with any text name, rather than just an address, I'd appreciate being told.
The context is that I am diagnosing a crash that happens in both debug test and release test modes when my signal handler throws an exception inside a BOOST_CHECK_THROW
. The signal is triggered by std::raise(SIGFPE)
, though the type of signal raised does not seem to matter. The crash does not occur in non-test modes, even if I use some complicated tricks to allow the program to signal and throw several times.
//common includes
#include <chrono> // s
#include <csetjmp> // jmp_buf, longjmp, setjmp
#include <csignal> // raise, signal
#include <cstdlib> // set_terminate
#include <iostream> // cout
#include <stdexcept> // exception, runtime_error
#include <string> // string, to_string
#include <thread> // sleep_for
namespace {
void sig_handler(int sig){
std::signal(sig,SIG_DFL);
std::signal(sig,sig_handler);
throw std::runtime_error(std::string("Caught signal: ") +
std::to_string(sig) + "\n");
}
void install_sig_handler(){std::signal(SIGFPE,sig_handler);} //add signals here
struct sig{sig(){install_sig_handler();}};
} //anonymous namespace
#ifndef TEST //non-test build functions, global setup, and main
std::jmp_buf buffer;
volatile int count(0);
void oops(volatile int& count){ // can return before signal is handled
std::cout<<"oops(int&) call number "<< ++count <<"; about to raise SIGFPE: "
<<SIGFPE<<"\n";
std::raise(SIGFPE);
}
void uncaught_exception_handler(){
static bool tried_throw = false;
try {if(!tried_throw++) throw;} // get access to active exception
catch(std::exception const& err){std::cerr<<err.what();} // print error content
catch(...){std::cerr<<"Non-standard exception thrown.\n";}
//std::_Exit(1) // don't exit; demonstrate signal throw repeatability instead
tried_throw=false;
std::longjmp(buffer,count); // return to main
}
int main(int /*argc*/,char */*argv*/[]){
//CRANE::Process::get_instance(argv[0]).execute();
sig my_sig; //install_sig_handler() is ok instead
std::set_terminate(&uncaught_exception_handler);
if (setjmp(buffer)<10) oops(count);
return 0;
}
#else // test configuration
void testable_oops(){ // unlikely to return before signal is handled
std::cout<<"testable_oops() about to raise SIGFPE: "<<SIGFPE<<"\n";
std::raise(SIGFPE);
using namespace std::chrono_literals;
std::this_thread::sleep_for(2s);
}
#define BOOST_TEST_MODULE CRANETest
#include <boost/test/included/unit_test.hpp>
BOOST_GLOBAL_FIXTURE(sig);
BOOST_AUTO_TEST_SUITE(ProcessTest)
BOOST_AUTO_TEST_CASE(RegularException){
BOOST_CHECK_THROW(throw std::runtime_error("blah"),std::exception);
}
BOOST_AUTO_TEST_CASE(SignalConvertedToException) {
BOOST_CHECK_THROW(testable_oops(),std::exception);
}
BOOST_AUTO_TEST_SUITE_END()
#endif
Debug test build commands:
g++ -std=c++1z -DTEST "-IC:\\boost\\boost_1_61_0" -O0 -Og -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror -c -fmessage-length=0 "-isystemC:\\boost\\boost_1_61_0" -o "src\\temp.o" "..\\src\\temp.cpp"
g++ -o temp.exe "src\\temp.o"
Debug build commands:
g++ -std=c++1z "-IC:\\boost\\boost_1_61_0" -O0 -Og -g3 -pedantic -pedantic-errors -Wall -Wextra -Werror -c -fmessage-length=0 "-isystemC:\\boost\\boost_1_61_0" -o "src\\temp.o" "..\\src\\temp.cpp"
g++ -o temp.exe "src\\temp.o"
Release test build commands:
g++ -std=c++1z -DTEST "-IC:\\boost\\boost_1_61_0" -O3 -pedantic -pedantic-errors -Wall -Wextra -Werror -c -fmessage-length=0 "-isystemC:\\boost\\boost_1_61_0" -o "src\\temp.o" "..\\src\\temp.cpp"
g++ -o temp.exe "src\\temp.o"
Release build commands:
g++ -std=c++1z "-IC:\\boost\\boost_1_61_0" -O3 -pedantic -pedantic-errors -Wall -Wextra -Werror -c -fmessage-length=0 "-isystemC:\\boost\\boost_1_61_0" -o "src\\temp.o" "..\\src\\temp.cpp"
g++ -o temp.exe "src\\temp.o"
Release and debug output are identical:
C:\Users\chris.chiasson\Files\temp>.\Debug\temp.exe
oops(int&) call number 1; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 2; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 3; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 4; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 5; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 6; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 7; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 8; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 9; about to raise SIGFPE: 8
Caught signal: 8
oops(int&) call number 10; about to raise SIGFPE: 8
Caught signal: 8
Release test and debug test outputs are identical:
C:\Users\chris.chiasson\Files\temp>".\Release Test\temp.exe"
Running 2 test cases...
testable_oops() about to raise SIGFPE: 8
terminate called after throwing an instance of 'std::runtime_error'
what(): Caught signal: 8
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.