我們使用的標準模式是使用sigaction為 SIGSEGV 注冊自定義信號處理程式,然后在發生分段錯誤時使用backtrace函式遍歷堆疊并將其列印到某個檔案。在日志中進行回溯是一個很好的功能,但它會禁用作業系統寫入崩潰程式的完整轉儲,這非常有用。如何既可以捕獲 SIGSEGV,進行自定義處理,又如何像在默認操作的情況下一樣使作業系統創建完整的轉儲?
例如,我可以呼叫記住默認處理程式的 oldact 指標(如 man 中所述),然后直接從自定義處理程式中呼叫它嗎?不用說,我們需要崩潰來指示它發生的確切位置。因此,例如將處理程式重新注冊為舊值并在其他地方隱式崩潰程式將不起作用。
uj5u.com熱心網友回復:
您可以在處理信號后重置 sigaction。然后錯誤指令會在從處理程式回傳后重新運行,并再次錯誤,導致核心轉儲。
下面是一個例子:
#include <signal.h>
#include <unistd.h>
struct sigaction oldSA;
void handler(int signal)
{
const char msg[] = "Caught, should dump core now\n";
write(STDERR_FILENO, msg, sizeof msg - 1);
sigaction(SIGSEGV, &oldSA, NULL);
}
int main()
{
struct sigaction sa={0};
sa.sa_handler=handler;
sigaction(SIGSEGV, &sa, &oldSA);
int* volatile p=NULL;
*p=5; // cause segfault
}
示例運行:
$ gcc test.c -o test && ./test
Caught, should dump core now
Segmentation fault (core dumped)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/359445.html
上一篇:叉子似乎在不必要的時候復制
