Segmentation Fault
阿新 • • 發佈:2020-07-27
Segmentation fault in Linux
段錯誤應該就是訪問了不可訪問的記憶體,這個記憶體要麼是不存在的,要麼是受系統保護的。
- SIGSEGV是在訪問記憶體時發生的錯誤,它屬於記憶體管理的範疇
- SIGSEGV是一個使用者態的概念,是作業系統在使用者態程式錯誤訪問記憶體時所做出的處理
- 當用戶態程式訪問(訪問表示讀、寫或執行)不允許訪問的記憶體時,產生SIGSEGV
- 當用戶態程式以錯誤的方式訪問允許訪問的記憶體時,產生SIGSEGV
使用者態程式地址空間,特指程式可以訪問的地址空間範圍。如果廣義的說,一個程序的地址空間應該包括核心空間部分,只是它不能訪問而已。
SIGSEGV產生的可能情況
SIGSEGV在很多時候是由於指標越界引起的,但並不是所有的指標越界都會引發SIGSEGV。一個越界的指標,如果不引用它,是不會引起SIGSEGV的。而即使引用了一個越界的指標,也不一定引起SIGSEGV。
錯誤的訪問型別引起
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* ch = "hello world";
ch[1] = 'H';
return 0;
}
上述程式編譯沒有問題,但是執行時彈出SIGSEGV。此例中,”hello world”作為一個常量字串,在編譯後會被放在.rodata
.rodata
節會被合併到text segment與程式碼段放在一起,故其所處記憶體區域是隻讀的。這就是錯誤的訪問型別引起的SIGSEGV。
訪問了不屬於程序地址空間的記憶體
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)0xC0000fff;
*p = 10;
return 0;
}
還有一種可能,往受到系統保護的記憶體地址寫資料,最常見的就是給一個指標以0地址:
#include <stdio.h> #include <stdlib.h> int main() { int i = 0; scanf ("%d", i); /* should be used &i */ printf ("%d\n", i); return 0; }
訪問了不存在的記憶體
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = NULL;
*p = 1;
return 0;
}
在實際情況中,此例中的空指標可能指向使用者態地址空間,但其所指向的頁面實際不存在。
記憶體越界,陣列越界,變數型別不一致等
#include <stdio.h>
#include <stdlib.h>
int main()
{
char test[1];
printf("%c", test[10]);
return 0;
}
試圖把一個整數按照字串的方式輸出
#include <stdio.h>
#include <stdlib.h>
int main()
{
int b = 10;
printf("%s\n", b);
return 0;
}