如何解决如果堆栈溢出使进程崩溃,如何通过 libunwind 获取调用堆栈?
我尝试根据现实生活场景编写一段示例代码。场景如下:
- 程序正在调用递归函数
- 使用堆栈
- 程序崩溃了,只有操作系统上的核心转储作为有用信息
我正在尝试编写自己的崩溃处理程序,以获得更好的故障排除信息。我还认为,如果在当前阶段,并非所有堆栈溢出异常都被捕获和处理,这可能会很有用。我正在使用 SA_ONSTACK 为信号处理创建一个新堆栈。但是它只允许打印 1 行错误消息 "sig_handler: signal 11" 。但是我无法使用 libunwind 打印出崩溃的调用堆栈(同一段代码适用于堆损坏导致的信号 11 - 例如空指针)。
由于stackovflow,有人可以建议如何在编程SIGSEGV时打印调用堆栈吗?
我的测试代码如下:
#define UNW_LOCAL_ONLY
#include <execinfo.h>
#include <cstdlib> // free,exit
#include <unistd.h> // _exit
#include <csignal> // sigaction,signal type sigemptyset
#include <stdio.h>
#include <cxxabi.h>
#include <string.h>
#include <libunwind.h>
#include <errno.h>
#include <err.h>
#include <execinfo.h>
#define sigsegv_outp(x,...) fprintf(stderr,x "\n",##__VA_ARGS__)
void unwind() {
printf("start unwinding\n");
unw_cursor_t cursor;
unw_context_t context;
// Initialize cursor to current frame for local unwinding.
unw_getcontext(&context);
unw_init_local(&cursor,&context);
// Unwind frames one by one,going up the frame stack.
while (unw_step(&cursor) > 0) {
unw_word_t offset,pc;
unw_get_reg(&cursor,UNW_REG_IP,&pc);
if (pc == 0) {
break;
}
printf("ip 0x%lx:",pc);
char sym[256];
if (unw_get_proc_name(&cursor,sym,sizeof(sym),&offset) == 0) {
printf(" (%s+0x%lx) ",offset);
char* demangle_ptr = sym;
int ret_state;
char* demangled = abi::__cxa_demangle(sym,nullptr,&ret_state);
if (ret_state == 0) {
demangle_ptr = demangled;
}
printf(" -> %s+0x%lx\n",demangle_ptr,offset);
free(demangled);
} else {
printf(" Error: unable to obtain symbol name for this frame\n");
}
}
}
static void sig_handler(int signum,siginfo_t *si,void *ctx)
{
static const char *si_codes[3] = {"","SEGV_MAPERR","SEGV_ACCERR"};
// unw_context_t *context = ctx;
printf("%s: signal %d\n",__FUNCTION__,signum);
sigsegv_outp("Segmentation Fault!");
sigsegv_outp("info.si_signo = %d",signum);
sigsegv_outp("info.si_errno = %d",si->si_errno);
sigsegv_outp("info.si_code = %d (%s)",si->si_code,si_codes[si->si_code]);
sigsegv_outp("info.si_addr = %p",si->si_addr);
switch(signum ) {
case SIGSEGV:
printf("%s:ninatest: sigsegv %d\n",signum);
unwind();
break;
default:
break;
}
_exit(1);
}
void endless_stackFrames(void) {
while (true) {
endless_stackFrames();
}
}
}
static uint8_t alternate_stack[SIGSTKSZ];
void set_signal_handler()
{
{
stack_t ss = {};
ss.ss_sp = (void*)alternate_stack;
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
if (sigaltstack(&ss,NULL) != 0) { err(1,"sigaltstack"); }
}
{
struct sigaction sig_action = {};
sig_action.sa_sigaction = sig_handler;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK;
if (sigaction(SIGSEGV,&sig_action,"sigaction"); }
}
}
int main(int argc,char **argv) {
set_signal_handler();
endless_stackFrames();
return 0;
}
之后可以通过 g++ stack_overflow_test1.cpp -o stack_overflow_test1 -g -lunwind -Wall -std=c++11 构建 并通过 $LD_LIBRARY_PATH=/usr/local/lib ./stack_overflow_test1
执行版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。