हालांकि एक सही उत्तर प्रदान किया गया है जो बताता है कि GNU libc backtrace()
फ़ंक्शन 1 का उपयोग कैसे करें और मैंने अपना स्वयं का उत्तर प्रदान किया है जो बताता है कि सिग्नल हैंडलर से बैकट्रेस सुनिश्चित करने के लिए गलती 2 के वास्तविक स्थान पर , मैं नहीं देखता हूं backtrace से सी + + प्रतीकों उत्पादन demangling के किसी भी उल्लेख ।
C ++ प्रोग्राम से backtraces प्राप्त करते समय, आउटपुट को c++filt
1 से प्रतीकों को हटाने के लिए या सीधे 1 का उपयोग करके चलाया जा सकता है ।abi::__cxa_demangle
- 1 लिनक्स और ओएस एक्स
ध्यान दें कि
c++filt
और __cxa_demangle
जीसीसी विशिष्ट हैं
- 2 लिनक्स
निम्नलिखित सी ++ लिनक्स उदाहरण मेरे अन्य उत्तर के रूप में उसी सिग्नल हैंडलर का उपयोग करता है और यह दर्शाता है कि c++filt
प्रतीकों को गिराने के लिए कैसे उपयोग किया जा सकता है।
कोड :
class foo
{
public:
foo() { foo1(); }
private:
void foo1() { foo2(); }
void foo2() { foo3(); }
void foo3() { foo4(); }
void foo4() { crash(); }
void crash() { char * p = NULL; *p = 0; }
};
int main(int argc, char ** argv)
{
// Setup signal handler for SIGSEGV
...
foo * f = new foo();
return 0;
}
आउटपुट ( ./test
):
signal 11 (Segmentation fault), address is (nil) from 0x8048e07
[bt]: (1) ./test(crash__3foo+0x13) [0x8048e07]
[bt]: (2) ./test(foo4__3foo+0x12) [0x8048dee]
[bt]: (3) ./test(foo3__3foo+0x12) [0x8048dd6]
[bt]: (4) ./test(foo2__3foo+0x12) [0x8048dbe]
[bt]: (5) ./test(foo1__3foo+0x12) [0x8048da6]
[bt]: (6) ./test(__3foo+0x12) [0x8048d8e]
[bt]: (7) ./test(main+0xe0) [0x8048d18]
[bt]: (8) ./test(__libc_start_main+0x95) [0x42017589]
[bt]: (9) ./test(__register_frame_info+0x3d) [0x8048981]
डिमांगल्ड आउटपुट ( ./test 2>&1 | c++filt
):
signal 11 (Segmentation fault), address is (nil) from 0x8048e07
[bt]: (1) ./test(foo::crash(void)+0x13) [0x8048e07]
[bt]: (2) ./test(foo::foo4(void)+0x12) [0x8048dee]
[bt]: (3) ./test(foo::foo3(void)+0x12) [0x8048dd6]
[bt]: (4) ./test(foo::foo2(void)+0x12) [0x8048dbe]
[bt]: (5) ./test(foo::foo1(void)+0x12) [0x8048da6]
[bt]: (6) ./test(foo::foo(void)+0x12) [0x8048d8e]
[bt]: (7) ./test(main+0xe0) [0x8048d18]
[bt]: (8) ./test(__libc_start_main+0x95) [0x42017589]
[bt]: (9) ./test(__register_frame_info+0x3d) [0x8048981]
निम्नलिखित मेरे मूल उत्तर से सिग्नल हैंडलर पर बनाता है और abi::__cxa_demangle
प्रतीकों को प्रदर्शित करने के लिए कैसे उपयोग किया जा सकता है इसका प्रदर्शन करने के लिए उपरोक्त उदाहरण में सिग्नल हैंडलर को बदल सकता है। यह सिग्नल हैंडलर उपरोक्त उदाहरण के समान ध्वस्त आउटपुट उत्पन्न करता है।
कोड :
void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
{
sig_ucontext_t * uc = (sig_ucontext_t *)ucontext;
void * caller_address = (void *) uc->uc_mcontext.eip; // x86 specific
std::cerr << "signal " << sig_num
<< " (" << strsignal(sig_num) << "), address is "
<< info->si_addr << " from " << caller_address
<< std::endl << std::endl;
void * array[50];
int size = backtrace(array, 50);
array[1] = caller_address;
char ** messages = backtrace_symbols(array, size);
// skip first stack frame (points here)
for (int i = 1; i < size && messages != NULL; ++i)
{
char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
// find parantheses and +address offset surrounding mangled name
for (char *p = messages[i]; *p; ++p)
{
if (*p == '(')
{
mangled_name = p;
}
else if (*p == '+')
{
offset_begin = p;
}
else if (*p == ')')
{
offset_end = p;
break;
}
}
// if the line could be processed, attempt to demangle the symbol
if (mangled_name && offset_begin && offset_end &&
mangled_name < offset_begin)
{
*mangled_name++ = '\0';
*offset_begin++ = '\0';
*offset_end++ = '\0';
int status;
char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
// if demangling is successful, output the demangled function name
if (status == 0)
{
std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
<< real_name << "+" << offset_begin << offset_end
<< std::endl;
}
// otherwise, output the mangled function name
else
{
std::cerr << "[bt]: (" << i << ") " << messages[i] << " : "
<< mangled_name << "+" << offset_begin << offset_end
<< std::endl;
}
free(real_name);
}
// otherwise, print the whole line
else
{
std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
}
}
std::cerr << std::endl;
free(messages);
exit(EXIT_FAILURE);
}