我只是想知道如何報告分段故障。分段故障是如何報告的?
- 該過程將會死亡,顯然它不能報告它。
- shell不會肯定知道,除非進程傳遞了一個信號,這可能並非必然。
- 操作系統可能能夠做些什麼,但我不知道如何。
哪一個報告分段錯誤(只是一個例子),以及如何?
我只是想知道如何報告分段故障。分段故障是如何報告的?
哪一個報告分段錯誤(只是一個例子),以及如何?
該進程將會死亡,顯然它不能報告它。
這其實是錯誤的。它是可能安裝一個SIGSEGV
處理程序來替換默認的處理程序,它只是轉儲核心和死亡。預加載庫可以這樣做來捕獲分段違例,並使用可用的有限設施來通知在系統上運行的另一個進程,以便退出之前發生的事情。
如果您看看函數wait()
or waitpid()
,您會發現退出狀態中的某個位表示核心轉儲。 POSIX規範提到WIFSIGNALED
[原文如此]和WTERMSIG
以獲得終止該過程的信號。 POSIX規範沒有提到它,但是在Mac OS X(10.7.4)中,例如,有一個WCOREDUMP()
宏來測試是否創建了核心文件。
你可以有一些類似的代碼this將調用GDB命令轉儲呼叫跟蹤:
void BacktraceOnSegv() {
struct sigaction action = {};
action.sa_handler = DumpBacktrace;
if (sigaction(SIGSEGV, &action, NULL) < 0) {
perror("sigaction(SEGV)");
}
}
void DumpBacktrace(int) {
pid_t dying_pid = getpid();
pid_t child_pid = fork();
if (child_pid < 0) {
perror("fork() while collecting backtrace:");
} else if (child_pid == 0) {
char buf[1024];
sprintf(buf, "gdb -p %d -batch -ex bt 2>/dev/null | "
"sed '0,/<signal handler/d'", dying_pid);
const char* argv[] = {"sh", "-c", buf, NULL};
execve("/bin/sh", (char**)argv, NULL);
_exit(1);
} else {
waitpid(child_pid, NULL, 0);
}
_exit(1);
}
Here是支持更多的平臺上實現。
好吧,首先,當CPU嘗試訪問進程無法訪問的地址時,會發生分段錯誤。在最低級別,內存映射的實現必須檢測到,通常會產生中斷。內核接收該中斷,並且具有其他代碼段的地址表,每個代碼段用於處理該中斷。
當內核接收到該中斷時,它會將其轉換爲特定值(由於硬件架構和內核實現的具體細節不同,因此我的含義很模糊)。通常將SIGSEGV
定義爲具有值11,但確切值不重要;它在signal.h
中定義。
此時,信號值被傳遞到內核中的另一個表格,其中包含「信號處理程序」的地址。其中一個處理程序位於由SIGSEGV
表示的偏移處。除非你已經做了一些改變,否則這個地址通常是一個導致核心轉儲的例程,假設適當的限制允許,但你可以用你自己的例程地址替換它,它可以做你喜歡的任何事情。