eis/TestProject/json_test/src/segvCatch.h

98 lines
2.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 作者: leehomwu
* 日期: 2011-05-14
* 修订: 2011-06-11, 处理部分处理器会将出错时的 EIP 也入栈的情况
* 描述: 捕获段错误、浮点错误,输出发生错误时的具体位置、调用路径
* 使用: 在 main 函数所在文件包含该头文件即可
* 示例: 当发生段错误或浮点错误时会向STDOUT打印调用路径上的指令地址类似
signal[8] catched when running code at 80486f0
signal[8] catched when running code at 80488ea
signal[8] catched when running code at 80488d9
进一步运行命令行,解析指令地址:
addr2line 80486f0 80488ea 80488d9 -s -C -f -e
[可执行文件]
得到输出:
main
newsig.cpp:14
a()
kk.cpp:23
b()
kk.cpp:19
*/
#ifndef __SEGV_CATCH_H
#define __SEGV_CATCH_H
#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#ifndef __USE_GNU
#define __USE_GNU
#include <sys/ucontext.h>
#include <ucontext.h>
#undef __USE_GNU
#else
#include <sys/ucontext.h>
#include <ucontext.h>
#endif
#ifdef __cplusplus
static void initSegvCatch(void);
class C_SEGVCATCH {
public:
C_SEGVCATCH() { initSegvCatch(); }
};
static C_SEGVCATCH C_segv_catch;
#else
static void initSegvCatch(void) __attribute__((constructor));
#endif
static void OnSIGSEGV(int, siginfo_t*, void*);
static void initSegvCatch() {
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = OnSIGSEGV;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0 || sigaction(SIGFPE, &act, NULL) < 0) {
perror("sigaction:");
}
}
static void OnSIGSEGV(int signum, siginfo_t* info, void* ptr) {
static int iTime;
if (iTime++ >=
1) { /* 容错处理:如果访问 ucontext_t 结构体时产生错误会进入该分支 */
printf("ReEnter %s is not allowed!\n", __FUNCTION__);
abort();
}
void* array[25];
int nSize = backtrace(array, sizeof(array) / sizeof(array[0]));
int i;
for (i = nSize - 3; i > 2; i--) { /* 头尾几个地址不必输出 */
/* 对array修正一下使地址指向正在执行的代码 */
printf("signal[%d] catched when running code at %x\n", signum,
(long)array[i] - 1);
}
if (NULL != ptr) {
ucontext_t* ptrUC = (ucontext_t*)ptr;
int* pgregs = (int*)(&(ptrUC->uc_mcontext.gregs));
int eip = pgregs[REG_RIP];
if (eip != (long)array[i]) { /* 有的处理器会将出错时的 EIP 入栈 */
printf("signal[%d] catched when running code at %x\n", signum,
(long)array[i] - 1);
}
printf("signal[%d] catched when running code at %x\n", signum,
eip); /* 出错时的指令地址 */
} else {
printf("signal[%d] catched when running code at unknown address\n", signum);
}
abort();
}
#endif // __SEGV_CATCH_H