這篇文章主要介紹“在C++ 代碼中怎么獲取函數(shù)調(diào)用棧信息”,在日常操作中,相信很多人在在C++ 代碼中怎么獲取函數(shù)調(diào)用棧信息問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”在C++ 代碼中怎么獲取函數(shù)調(diào)用棧信息”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
成都創(chuàng)新互聯(lián)是一家專業(yè)提供貴德企業(yè)網(wǎng)站建設,專注與網(wǎng)站設計、成都做網(wǎng)站、H5建站、小程序制作等業(yè)務。10年已為貴德眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進行中。
程序在執(zhí)行過程中 crash 是非常嚴重的問題,一般都應該在測試階段排除掉這些問題,但是總會有漏網(wǎng)之魚被帶到 release 階段。
因此,程序的日志系統(tǒng)需要偵測這種情況,在代碼崩潰的時候獲取函數(shù)調(diào)用棧信息,為 debug 提供有效的信息。
需要處理哪些異常信號
#include <execinfo.h> #include <cxxabi.h> #include <signal.h> const std::map<int, std::string> Signals = { {SIGINT, "SIGINT"}, {SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGILL, "SIGILL"}, {SIGSEGV, "SIGSEGV"} // 可以添加其他信號 };
注冊信號處理函數(shù)
struct sigaction action; sigemptyset(&action.sa_mask); action.sa_sigaction = &sigHandler; action.sa_flags = SA_SIGINFO; for (const auto &sigPair : Signals) { if (sigaction(sigPair.first, &action, NULL) < 0) fprintf(stderr, "Error: sigaction failed! \n"); }
void sigHandler(int signum, siginfo_t *info, void *ctx) { const size_t dump_size = 50; void *array[dump_size]; int size = backtrace(array, dump_size); char **symbols = backtrace_symbols(array, size); std::ostringstream oss; for (int i = 0; i < size; ++i) { char *mangleName = 0; char *offsetBegin = 0; char *offsetEnd = 0; for (char *p = symbols[i]; *p; ++p) { if ('(' == *p) { mangleName = p; } else if ('+' == *p) { offsetBegin = p; } else if (')' == *p) { offsetEnd = p; break; } } if (mangleName && offsetBegin && offsetEnd && mangleName < offsetBegin) { *mangleName++ = '\0'; *offsetBegin++ = '\0'; *offsetEnd++ = '\0'; int status; char *realName = abi::__cxa_demangle(mangleName, 0, 0, &status); if (0 == status) oss << "\tstack dump [" << i << "] " << symbols[i] << " : " << realName << "+"; else oss << "\tstack dump [" << i << "] " << symbols[i] << mangleName << "+"; oss << offsetBegin << offsetEnd << std::endl; free(realName); } else { oss << "\tstack dump [" << i << "] " << symbols[i] << std::endl; } } free(symbols); oss << std::endl; std::cout << oss.str(); // 打印函數(shù)調(diào)用棧信息 }
在 Windows 平臺下的代碼實現(xiàn),參考了國外某個老兄的代碼,如下:
#include <windows.h> #include <dbghelp.h> SetUnhandledExceptionFilter(exceptionHandler);
void exceptionHandler(LPEXCEPTION_POINTERS info) { CONTEXT *context = info->ContextRecord; std::shared_ptr<void> RaiiSysCleaner(nullptr, [&](void *) { SymCleanup(GetCurrentProcess()); }); const size_t dumpSize = 64; std::vector<uint64_t> frameVector(dumpSize); DWORD machine_type = 0; STACKFRAME64 frame = {}; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat; #ifdef _M_IX86 frame.AddrPC.Offset = context->Eip; frame.AddrFrame.Offset = context->Ebp; frame.AddrStack.Offset = context->Esp; machine_type = IMAGE_FILE_MACHINE_I386; #elif _M_X64 frame.AddrPC.Offset = context->Rip; frame.AddrFrame.Offset = context->Rbp; frame.AddrStack.Offset = context->Rsp; machine_type = IMAGE_FILE_MACHINE_AMD64; #elif _M_IA64 frame.AddrPC.Offset = context->StIIP; frame.AddrFrame.Offset = context->IntSp; frame.AddrStack.Offset = context->IntSp; machine_type = IMAGE_FILE_MACHINE_IA64; frame.AddrBStore.Offset = context.RsBSP; frame.AddrBStore.Mode = AddrModeFlat; #else frame.AddrPC.Offset = context->Eip; frame.AddrFrame.Offset = context->Ebp; frame.AddrStack.Offset = context->Esp; machine_type = IMAGE_FILE_MACHINE_I386; #endif for (size_t index = 0; index < frameVector.size(); ++index) { if (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), &frame, context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { frameVector[index] = frame.AddrPC.Offset; } else { break; } } std::string dump; const size_t kSize = frameVector.size(); for (size_t index = 0; index < kSize && frameVector[index]; ++index) { dump += getSymbolInfo(index, frameVector); dump += "\n"; } std::cout << dump; }
主要是利用了 StackWalk64 這個函數(shù),從地址轉換為函數(shù)名稱。
到此,關于“在C++ 代碼中怎么獲取函數(shù)調(diào)用棧信息”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
本文題目:在C++代碼中怎么獲取函數(shù)調(diào)用棧信息
本文網(wǎng)址:http://jinyejixie.com/article30/pdcpso.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、自適應網(wǎng)站、域名注冊、網(wǎng)站導航、網(wǎng)站制作、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)