免费A级毛片无码专区网站-成人国产精品视频一区二区-啊 日出水了 用力乖乖在线-国产黑色丝袜在线观看下-天天操美女夜夜操美女-日韩网站在线观看中文字幕-AV高清hd片XXX国产-亚洲av中文字字幕乱码综合-搬开女人下面使劲插视频

深入剖析Sgementation fault原理

深入剖析Sgementation fault原理前言我們在日常的編程當中,我們很容易遇到的一個程序崩潰的錯誤就是segmentation fault,在本篇文章當中將主要分析段錯誤發(fā)生的原因!
Sgementation fault發(fā)生的原因發(fā)生Sgementation fault的直接原因是,程序收到一個來自內(nèi)核的SIGSEGV信號,如果是你的程序?qū)е碌膬?nèi)核給進程發(fā)送這個信號的話,那么就是你的程序正在讀或者寫一個沒有分配的頁面或者你沒有讀或者寫的權(quán)限 。這個信號的來源有兩個:

  • 程序的非法訪問,自身程序的指令導致的Sgementation fault 。
  • 另外一種是由別的程序直接發(fā)送SIGSEGV信號給這個進程 。
在類Linux系統(tǒng)中,內(nèi)核給進程發(fā)送的信號為SIGGEV,信號對應數(shù)字為11,在Linux當中信號對應的數(shù)字情況大致如下所示:
1) SIGHUP2) SIGINT3) SIGQUIT4) SIGILL5) SIGTRAP 6) SIGABRT7) SIGBUS8) SIGFPE9) SIGKILL 10) SIGUSR111) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+338) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+843) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-758) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX當一個程序發(fā)生 segmentation fault 的時候,這個程序的退出碼 exitcode 等于 139!
深入剖析Sgementation fault原理

文章插圖
發(fā)生 segmentation fault 的一個主要的原因是我們自己的程序發(fā)生非法訪問內(nèi)存,同時別的程序給這個進程發(fā)送 SIGSGEV 信號也會導致我們的程序發(fā)生 segmentation fault 錯誤 。
比如下面的程序就是自己發(fā)生的段錯誤(發(fā)生了越界訪問):
#include <stdio.h>int main() {int arr[10];arr[1 << 20] = 100; // 會導致 segmentation faultprintf("arr[12] = %d\n", arr[1 << 20]); // 會導致 segmentation faultreturn 0;}下面是一個別的程序給其他程序發(fā)送SIGSGEV信號會導致其他進程出現(xiàn)段錯誤(下面的終端給上面終端的進程號等于504092的程序發(fā)送了一個信號值等于11(就是SIGGSGEV)信號,讓他發(fā)生段錯誤):
深入剖析Sgementation fault原理

文章插圖
自定義信號處理函數(shù)【深入剖析Sgementation fault原理】操作系統(tǒng)允許我們自己定義函數(shù),當某些信號被發(fā)送到進程之后,進程就會去執(zhí)行這些函數(shù),而不是系統(tǒng)默認的程序(比如說SIGSEGV默認函數(shù)是退出程序) 。下面來看我們重寫SIGINT信號的處理函數(shù),當一個程序在終端執(zhí)行的時候我們按下ctrl+c,這個正在執(zhí)行的程序就會收到一個來自內(nèi)核的SIGINT信號:
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <string.h>void sig(int n) { // 參數(shù) n 表示代表信號的數(shù)值char* str = "signal number = %d\n";char* out = malloc(128);sprintf(out, str, n);write(STDOUT_FILENO, out, strlen(out));free(out);}int main() {signal(SIGINT, sig); // 這行代碼就是注冊函數(shù) 當進程收到 SIGINT 信號的時候就執(zhí)行 sig 函數(shù)printf("pid = %d\n", getpid());while (1){sleep(1);}return 0;}
深入剖析Sgementation fault原理

文章插圖
首先我們需要知道,當我們在終端啟動一個程序之后,如果我們在終端按下ctrl+c終端會給當前正在運行的進程以及他的子進程發(fā)送SIGINT信號,SIGINT信號的默認處理函數(shù)就是退出程序,但是我們可以捕獲這個信號,重寫處理函數(shù) 。在上面的程序當中我們就自己重寫了SIGINT的處理函數(shù),當進程接收到 SIGINT 信號的時候就會觸發(fā)函數(shù) sig。上面程序的輸出印證了我們的結(jié)果 。

經(jīng)驗總結(jié)擴展閱讀