1. 程式人生 > >linux中的段錯誤

linux中的段錯誤

1. 段錯誤是什麼?

段錯誤:Segmentation Fault,簡單說,段錯誤是指訪問的記憶體超出了系統給這個程式所設定的記憶體空間,例如訪問了不存在的記憶體地址、訪問了系統保護的記憶體地址、訪問了只讀的記憶體地址等情況。這裡貼出“段錯誤的準確定義:

A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors. 


On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception. 

2. 段錯誤產生的原因

(1)訪問不存在的記憶體地址

#include <stdio.h>
int main()                                                                                           
{
    int *ptr = NULL;
    *ptr = 0;
}
(2) 訪問系統保護的記憶體地址

#include <stdio.h> 
int main()  
{           
    int *ptr = (int*)0;
    *ptr = 100;
}
(3)訪問了只讀的記憶體地址

#include <stdio.h>  
#include <string.h>                                                                                  
int main()          
{                   
    int *ptr = "test"; 
    strcpy(ptr, "TEST");
}
(4)棧溢位

#include <stdio.h>
int main() 
{          
    main();                                                                                          
}

3. 段錯誤資訊的獲取

(1)dmesg

dmesg可以在應用程式crash掉時,顯示核心中儲存的相關資訊。

通過dmesg可以檢視傳送段錯誤的程式名稱、引起段錯誤傳送的記憶體地址、指令指標地址、堆疊指標地址、錯誤程式碼、錯誤原因等。

(2.3)的錯誤如下:

Process 3199(a.out) has RLIMIT_CORE set to 0
Aborting core
a.out[3251]: segfault at bf289ffc ip 080484a6 sp bf28a000 error 6 in a.out[8048000+1000]
Process 3251(a.out) has RLIMIT_CORE set to 0
Aborting core
a.out[3285]: segfault at 8048590 ip 080484b0 sp bfc81af8 error 7 in a.out[8048000+1000]
Process 3285(a.out) has RLIMIT_CORE set to 0
Aborting core
Process 3306(a.out) has RLIMIT_CORE set to 0
Aborting core
a.out[3332]: segfault at 8048590 ip 080484b0 sp bf97a108 error 7 in a.out[8048000+1000]
a.out[3361]: segfault at 8048590 ip 080484b0 sp bfc41178 error 7 in a.out[8048000+1000]
a.out[3385]: segfault at 80485d0 ip 080484f9 sp bff79e10 error 7 in a.out[8048000+1000]
a.out[3443]: segfault at 8048590 ip 080484b0 sp bf9cd278 error 7 in a.out[8048000+1000]
(2) -g

用gdb檢視

(3)nm命令,可以幫助檢視哪裡傳送段錯誤

(4)ldd命令,可以檢視二進位制程式的共享連結庫依賴,包括庫名稱、起始地址,用於確定段錯誤是發生在自己程式中還是依賴的共享庫中。

4. 除錯方法

(1)printf輸出資訊

(2)使用gdb除錯程式

程式2.3中結果是

Program received signal SIGSEGV, Segmentation fault.
0x080484b0 in main ()
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.1.i686 libgcc-4.4.7-16.el6.i686 libstdc++-4.4.7-16.el6.i686
(3)生成core檔案。

在一些linux版本下預設不產生core檔案,檢視下系統core檔案的大小限制:

@: ulimit -c
0
@:ulimit -c 1024
@:ulimit -c
1024

再執行程式即可產生core

5. 最後注意事項

(1) 出現段錯誤時,首先應該想到段錯誤的定義,從它出發考慮引發錯誤的原因。

(2) 在使用指標時,定義了指標後記得初始化指標,在使用的時候記得判斷是否為NULL

(3) 在使用陣列時,注意陣列是否被初始化,陣列下標是否越界,陣列元素是否存在等。

(4) 在訪問變數時,注意變數所佔地址空間是否已經被程式釋放掉。

(5) 在處理變數時,注意變數的格式控制是否合理等。

原文地址http://blog.163.com/[email protected]/blog/static/17361234820122761525799/