è¿ç¨å¨è¿è¡è¿ç¨ä¸éå°é»è¾é误, æ¯å¦é¤é¶, 空æéçç, ç³»ç»ä¼è§¦åä¸ä¸ªè½¯ä»¶ä¸æ.
è¿ä¸ªä¸æä¼ä»¥ä¿¡å·çæ¹å¼éç¥è¿ç¨, è¿äºä¿¡å·çé»è®¤å¤çæ¹å¼æ¯ç»æè¿ç¨.
åçè¿ç§æ
åµ, æ们就认为è¿ç¨å´©æºäº.
è¿ç¨å´©æºå, æ们ä¼å¸æç¥éå®æ¯ä¸ºä½å´©æºç, æ¯åªä¸ªå½æ°, åªè¡ä»£ç å¼èµ·çé误.
å¦å¤, å¨è¿ç¨éåºå, æ们è¿å¸æåä¸äºååå¤ç, æ¯å¦ææäºæ°æ®åå
¥æ°æ®åº, çç.
ä¸é¢, æä¼ä»ç»ä¸äºææ¯æ¥è¾¾æè¿ä¸¤ä¸ªç®æ .
1. å¨coreæ件ä¸æ¥çå æ ä¿¡æ¯
å¦æè¿ç¨å´©æºæ¶, æ们è½çå°å½æ¶çå æ ä¿¡æ¯, å°±è½å¾å¿«å®ä½å°é误ç代ç .
å¨ gcc ä¸å å
¥ -g é项, å¯æ§è¡æ件ä¸ä¾¿ä¼å
å«è°è¯ä¿¡æ¯. è¿ç¨å´©æºå, ä¼çæä¸ä¸ª core æ件.
æ们å¯ä»¥ç¨ gdb æ¥çè¿ä¸ª core æ件, ä»èç¥éè¿ç¨å´©æºæ¶çç¯å¢.
å¨è°è¯é¶æ®µ, coreæ件è½ç»æ们带æ¥å¾å¤ä¾¿å©. ä½æ¯å¨æ£å¼ç¯å¢ä¸, å®æå¾å¤§çå±é:
1. å
å«è°è¯ä¿¡æ¯çå¯æ§è¡æ件ä¼å¾å¤§. 并ä¸è¿è¡é度ä¹ä¼å¤§å¹
éä½.
2. ä¸ä¸ª core æ件常常å¾å¤§, å¦æè¿ç¨é¢ç¹å´©æº, 硬çèµæºä¼åå¾å¾ç´§å¼ .
æ以, å¨æ£å¼ç¯å¢ä¸è¿è¡çç¨åº, ä¸ä¼å
å«è°è¯ä¿¡æ¯.
å®çcoreæ件ç大å°, æ们ä¼æå®è®¾ä¸º0, ä¹å°±æ¯ä¸ä¼è¾å
¥coreæ件.
å¨è¿ä¸ªåæä¸, æ们å¦ä½å¾å°è¿ç¨çå æ ä¿¡æ¯å¢?
2. å¨æè·å线ç¨çå æ
c è¯è¨æä¾äº backtrace å½æ°, éè¿è¿ä¸ªå½æ°å¯ä»¥å¨æçè·åå½å线ç¨çå æ .
è¦ä½¿ç¨ backtrace å½æ°, æ两ç¹è¦æ±:
1. ç¨åºä½¿ç¨çæ¯ ELF äºè¿å¶æ ¼å¼.
2. ç¨åºè¿æ¥æ¶ä½¿ç¨äº -rdynamic é项.
-rdynamicå¯ç¨æ¥éç¥é¾æ¥å¨å°ææ符å·æ·»å å°å¨æ符å·è¡¨ä¸, è¿äºä¿¡æ¯æ¯ -g é项çä¿¡æ¯è¦å°å¾å¤.
ä¸é¢æ¯å°è¦ç¨å°çå½æ°è¯´æ:
#include <execinfo.h>
int backtrace(void **buffer,int size);
ç¨äºè·åå½å线ç¨çè°ç¨å æ , è·åçä¿¡æ¯å°ä¼è¢«åæ¾å¨bufferä¸, å®æ¯ä¸ä¸ªæéå表ã
åæ° size ç¨æ¥æå®bufferä¸å¯ä»¥ä¿åå¤å°ä¸ªvoid* å
ç´ ã
å½æ°è¿åå¼æ¯å®é
è·åçæé个æ°, æ大ä¸è¶
è¿size大å°
注æ: æäºç¼è¯å¨çä¼åé项对è·åæ£ç¡®çè°ç¨å æ æå¹²æ°,
å¦å¤å
èå½æ°æ²¡æå æ æ¡æ¶; å é¤æ¡æ¶æéä¹ä¼å¯¼è´æ æ³æ£ç¡®è§£æå æ å
容;
char ** backtrace_symbols (void *const *buffer, int size)
æä»backtraceå½æ°è·åçä¿¡æ¯è½¬å为ä¸ä¸ªå符串æ°ç».
åæ°bufferåºè¯¥æ¯ä»backtraceå½æ°è·åçæéæ°ç»,
sizeæ¯è¯¥æ°ç»ä¸çå
ç´ ä¸ªæ°(backtraceçè¿åå¼) ;
å½æ°è¿åå¼æ¯ä¸ä¸ªæåå符串æ°ç»çæé, å®ç大å°åbufferç¸å.
æ¯ä¸ªå符串å
å«äºä¸ä¸ªç¸å¯¹äºbufferä¸å¯¹åºå
ç´ çå¯æå°ä¿¡æ¯.
å®å
æ¬å½æ°åï¼å½æ°çå移å°å, åå®é
çè¿åå°å.
该å½æ°çè¿åå¼æ¯éè¿mallocå½æ°ç³è¯·ç空é´, å æ¤è°ç¨è
å¿
须使ç¨freeå½æ°æ¥éæ¾æé.
注æ: å¦æä¸è½ä¸ºå符串è·å足å¤ç空é´, å½æ°çè¿åå¼å°ä¼ä¸ºNULL.
void backtrace_symbols_fd (void *const *buffer, int size, int fd)
ä¸backtrace_symbols å½æ°å
·æç¸åçåè½,
ä¸åçæ¯å®ä¸ä¼ç»è°ç¨è
è¿åå符串æ°ç», èæ¯å°ç»æåå
¥æ件æ述符为fdçæ件ä¸,æ¯ä¸ªå½æ°å¯¹åºä¸è¡.
3. ææä¿¡å·
æ们å¸æå¨è¿ç¨å´©æºæ¶æå°å æ , æ以æ们éè¦ææå°ç¸åºçä¿¡å·. æ¹æ³å¾ç®å.
#include <signal.h>
void (*signal(int signum,void(* handler)(int)))(int); ãã
æè
ï¼ typedef void(*sig_t) ( int ); ãã
sig_t signal(int signum,sig_t handler); ãã
åæ°è¯´æï¼ ã
第ä¸ä¸ªåæ°signumææäºæè¦å¤ççä¿¡å·ç±»åï¼å®å¯ä»¥æ¯é¤äºSIGKILLåSIGSTOPå¤çä»»ä½ä¸ç§ä¿¡å·ã ã
第äºä¸ªåæ°handleræè¿°äºä¸ä¿¡å·å
³èçå¨ä½ï¼å®å¯ä»¥å以ä¸ä¸ç§å¼ï¼ ãã
1. ä¸ä¸ªè¿åå¼ä¸ºæ£æ°çå½æ°çå°å, ä¹å°±æ¯æ们çä¿¡å·å¤çå½æ°.
è¿ä¸ªå½æ°åºæå¦ä¸å½¢å¼çå®ä¹ï¼ int func(int sig); ããsigæ¯ä¼ éç»å®çå¯ä¸åæ°ã
æ§è¡äºsignal()è°ç¨åï¼è¿ç¨åªè¦æ¥æ¶å°ç±»å为sigçä¿¡å·ï¼ä¸ç®¡å
¶æ£å¨æ§è¡ç¨åºçåªä¸é¨åï¼å°±ç«å³æ§è¡func()å½æ°ã
å½func()å½æ°æ§è¡ç»æåï¼æ§å¶æè¿åè¿ç¨è¢«ä¸æçé£ä¸ç¹ç»§ç»æ§è¡ããã
2. SIGIGN, 忽ç¥è¯¥ä¿¡å·.
3. SIGDFL, æ¢å¤ç³»ç»å¯¹ä¿¡å·çé»è®¤å¤çã
è¿åå¼ï¼ è¿åå
åçä¿¡å·å¤çå½æ°æéï¼å¦ææé误åè¿åSIG_ERR(-1)ã ãã
注æï¼ ãã
å½ä¸ä¸ªä¿¡å·çä¿¡å·å¤çå½æ°æ§è¡æ¶ï¼å¦æè¿ç¨åæ¥æ¶å°äºè¯¥ä¿¡å·ï¼è¯¥ä¿¡å·ä¼èªå¨è¢«å¨åèä¸ä¼ä¸æä¿¡å·å¤çå½æ°çæ§è¡ï¼
ç´å°ä¿¡å·å¤çå½æ°æ§è¡å®æ¯åéæ°è°ç¨ç¸åºçå¤çå½æ°ã
å¦æå¨ä¿¡å·å¤çå½æ°æ§è¡æ¶è¿ç¨æ¶å°äºå
¶å®ç±»åçä¿¡å·ï¼è¯¥å½æ°çæ§è¡å°±ä¼è¢«ä¸æããã
å¨ä¿¡å·åç跳转å°èªå®çhandlerå¤çå½æ°æ§è¡åï¼ç³»ç»ä¼èªå¨å°æ¤å¤çå½æ°æ¢ååæ¥ç³»ç»é¢è®¾çå¤çæ¹å¼ï¼
å¦æè¦æ¹åæ¤æä½è¯·æ¹ç¨sigaction()ããã
4. å®ä¾
ä¸é¢æ们å®é
ç¼ç , ççå
·ä½å¦ä½å¨ææå°ä¿¡å·å, æå°è¿ç¨å æ , ç¶åç»æè¿ç¨.
#include <iostream>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <execinfo.h>
#include <fcntl.h>
#include <map>
using namespace std;
map<int, string> SIG_LIST;
#define SET_SIG(sig) SIG_LIST[sig] = #sig;
void SetSigList(){
SIG_LIST.clear();
SET_SIG(SIGILL)//éæ³æ令
SET_SIG(SIGBUS)//æ»çº¿é误
SET_SIG(SIGFPE)//æµ®ç¹å¼å¸¸
SET_SIG(SIGABRT)//æ¥èªabortå½æ°çç»æ¢ä¿¡å·
SET_SIG(SIGSEGV)//æ æçåå¨å¨å¼ç¨(段é误)
SET_SIG(SIGPIPE)//åä¸ä¸ªæ²¡æ读ç¨æ·ç管éååæä½
SET_SIG(SIGTERM)//软件ç»æ¢ä¿¡å·
SET_SIG(SIGSTKFLT)//åå¤çå¨ä¸çæ æ
é
SET_SIG(SIGXFSZ)//æ件大å°è¶
åºéå¶
SET_SIG(SIGTRAP)//è·è¸ªé·é±
}
string& GetSigName(int sig){
return SIG_LIST[sig];
}
void SaveBackTrace(int sig){
//æå¼æ件
time_t tSetTime;
time(&tSetTime);
tm* ptm = localtime(&tSetTime);
char fname[256] = {0};
sprintf(fname, "core.%d-%d-%d_%d_%d_%d",
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
FILE* f = fopen(fname, "a");
if (f == NULL){
exit(1);
}
int fd = fileno(f);
//éå®æ件
flock fl;
fl.l_type = F_WRLCK;
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
fl.l_pid = getpid();
fcntl(fd, F_SETLKW, &fl);
//è¾åºç¨åºçç»å¯¹è·¯å¾
char buffer[4096];
memset(buffer, 0, sizeof(buffer));
int count = readlink("/proc/self/exe", buffer, sizeof(buffer));
if(count > 0){
buffer[count] = '\n';
buffer[count + 1] = 0;
fwrite(buffer, 1, count+1, f);
}
//è¾åºä¿¡æ¯çæ¶é´
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "Dump Time: %d-%d-%d %d:%d:%d\n",
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
fwrite(buffer, 1, strlen(buffer), f);
//线ç¨åä¿¡å·
sprintf(buffer, "Curr thread: %d, Catch signal:%s\n",
pthread_self(), GetSigName(sig).c_str());
fwrite(buffer, 1, strlen(buffer), f);
//å æ
void* DumpArray[256];
int nSize = backtrace(DumpArray, 256);
sprintf(buffer, "backtrace rank = %d\n", nSize);
fwrite(buffer, 1, strlen(buffer), f);
if (nSize > 0){
char** symbols = backtrace_symbols(DumpArray, nSize);
if (symbols != NULL){
for (int i=0; i<nSize; i++){
fwrite(symbols[i], 1, strlen(symbols[i]), f);
fwrite("\n", 1, 1, f);
}
free(symbols);
}
}
//æ件解éåå
³é, æåç»æ¢è¿ç¨
fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl);
fclose(f);
exit(1);
}
void SetSigCatchFun(){
map<int, string>::iterator it;
for (it=SIG_LIST.begin(); it!=SIG_LIST.end(); it++){
signal(it->first, SaveBackTrace);
}
}
void Fun(){
int a = 0;
int b = 1 / a;
}
static void* ThreadFun(void* arg){
Fun();
return NULL;
}
int main(){
SetSigList();
SetSigCatchFun();
printf("main thread id = %d\n", (pthread_t)pthread_self());
pthread_t pid;
if (pthread_create(&pid, NULL, ThreadFun, NULL)){
exit(1);
}
printf("fun thread id = %d\n", pid);
for(;;){
sleep(1);
}
return 0;
}
æ件å为 bt.cpp
ç¼è¯: g++ bt.cpp -rdynamic -I /usr/local/include -L /usr/local/lib -pthread -o bt
主线ç¨åå»ºäº fun 线ç¨, fun 线ç¨æä¸ä¸ªé¤é¶é误, ç³»ç»æåº SIGFPE ä¿¡å·.
该信å·ä½¿ fun 线ç¨ä¸æ, æ们注åç SaveBackTrace å½æ°æè·å°è¿ä¸ªä¿¡å·, æå°ç¸å
³ä¿¡æ¯, ç¶åç»æ¢è¿ç¨.
å¨è¾åºçcoreæ件ä¸, æ们å¯ä»¥çå°ç®åçå æ ä¿¡æ¯.
5. ååå¤ç
å¨ä¸é¢çä¾åä¸, fun 线ç¨è¢« SIGFPE ä¸æ, 转èæ§è¡ SaveBackTrace å½æ°.
æ¤æ¶, main 线ç¨ä»ç¶å¨æ£å¸¸è¿è¡.
å¦ææ们æ SaveBackTrace å½æ°æåç exit(1); æ¿æ¢æ for(;;)sleep(1);
main 线ç¨å°±å¯ä»¥ä¸ç´æ£å¸¸çè¿è¡ä¸å».
å©ç¨è¿ä¸ªç¹ç¹, æ们å¯ä»¥åå¾å¤å
¶å®äºæ
.
游æçæå¡å¨è¿ç¨å¸¸å¸¸æè¿äºçº¿ç¨:
ç½ç»çº¿ç¨, æ°æ®åºçº¿ç¨, ä¸å¡å¤ç线ç¨. å¼åé»è¾é误ç代ç 常常ä½äºä¸å¡å¤ç线ç¨.
èæ°æ®åºçº¿ç¨ç±äºåè½ç¨³å®, é»è¾ç®å, æ¯åå强壮ç.
é£ä¹, å¦æä¸å¡å¤ç线ç¨æé»è¾é误, æ们ææå°ä¿¡å·å, å¯ä»¥å¨ä¿¡å·å¤çå½æ°çæå,
éç¥æ°æ®åºçº¿ç¨ä¿å游ææ°æ®.
ç´å°æ°æ®åºçº¿ç¨æ游æä¿¡æ¯å
¨é¨åå
¥æ°æ®åº, ä¿¡å·å¤çå½æ°æè¿å.
è¿æ ·, æå¡å¨å®æºä¸ä¼å¯¼è´åæ¡£, æ失被大大éä½.
è¦å®ç°è¿ä¸ªæºå¶, è¦æ±æ°æ®åºæ¨¡ååä¸å¡å¤ç模åå
·æä½è¦å度.
å½ç¶, å®é
åºç¨çæ¶å, è¿æ许å¤ç»èè¦èè.
æ¯å¦, ä¸å¡å¤ç线ç¨æ£å¨å¤çç©å®¶çæ°æ®, ç±äºåçä¸å¯é¢ç¥çé误, ç©å®¶çæ°æ®è¢«æåäº, è¿äºç©å®¶çæ°æ®å°±ä¸åºè¯¥è¢«åå
¥æ°æ®åº.
温馨提示:答案为网友推荐,仅供参考