Segmentation Fault


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節(GCC),最后鏈接生成目標程序時.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;
}

棧溢出了,有時SIGSEGV,有時卻啥都沒發生


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM