1
#include
2
int
3
main()
4
01
#include
02
03
int
04
main()
05
1
#include
2
int
3
main()
4
這裡是比較極端的例子,但是有時候可能是會出現的,是個明顯的陣列越界的問題
或者是這個位址是根本就不存在的
例子4:
1
#include
2
int
3
main()
4
我們試圖把乙個整數按照字串的方式輸出出去,這是什麼問題呢?
由於還不熟悉除錯動態鏈結庫,所以
我只是找到了printf的源**的這裡
宣告部分:
01
int
pos =0 ,cnt_printed_chars =0 ,i ;
02
unsigned
char
*chptr ;
03
va_list
ap ;
04
/* %s格式控制部分:*/
05
case
's'
:
06
chptr =
va_arg
(ap ,unsigned
char
*);
07
i =0 ;
08
while
(chptr [i ])
09
由於我沒有仔細分析**,大致的原因也可能是位址越界的原因?不過我可不確定哦。
如果大家知道怎麼除錯printf函式,麻煩幫忙找出越界的真正原因吧,這個段錯誤也可能是
處在va_start和va_arg等函式裡頭?或者直接看看這個這裡的printf源**的分析,看看是否
可以找出出錯的地方:
類似的,還有諸如:sprintf等的格式控制問題
比如,試圖把char型或者是int的按照%s輸出或存放起來,如:
01
#include
02
#include
03
char
c='c';
04
int
i=10;
05
char
buf[100];
06
printf
("%s", c);
//試圖把char型按照字串格式輸出
07
printf
("%s", i);
//試圖把int型按照字串輸出
08
memset
(buf, 0, 100);
09
sprintf
(buf, "%s", c);
//試圖把char型按照字串格式轉換
10
memset
(buf, 0, 100);
11
sprintf
(buf, "%s", i);
//試圖把int型按照字串轉換
3)其他
其實大概的原因都是一樣的,就是段錯誤的定義。
但是更多的容易出錯的地方就要自己不斷積累,不段發現,或者吸納前人已經積累的經驗,並且注意避免再次發生。
例如:<1>定義了指標後記得初始化,在使用的時候記得判斷是否為null
<2>在使用陣列的時候是否被初始化,陣列下標是否越界,陣列元素是否存在等
<3>在變數處理的時候變數的格式控制是否合理等
乙個比較不錯的例子:
我在進行乙個多執行緒程式設計的例子裡頭,定義了乙個執行緒陣列
#define thread_max_num
pthread_t thread[thread_max_num];
用pthread_create建立了各個執行緒,然後用pthread_join來等待執行緒的結束
剛開始我就直接等待,在建立執行緒都成功的時候,pthread_join能夠順利等待各個執行緒結束
但是一旦建立執行緒失敗,那用pthread_join來等待那個本不存在的執行緒時自然會存在訪問不存在的記憶體的情況,從而導致段錯誤的發生
後來通過不斷除錯和思考,並且得到網路上資料的幫助,找到了上面的出錯原因和解決辦法
解決辦法是:
在建立執行緒之前,先初始化我們的執行緒陣列
在等待執行緒的結束的時候,判斷執行緒是否為我們的初始值
如果是的話,說明我們的執行緒並沒有建立成功,所以就不能等拉。
上面給出了很常見的幾種出現段錯誤的地方,這樣在遇到它們的時候就容易避免拉。
但是人有時候肯定也會有疏忽的,甚至可能還是會經常出現上面的問題或者其他常見的問題
所以對於一些大型一點的程式,如何跟蹤並找到程式中的段錯誤位置就是需要掌握的一門技巧拉。
4。如何發現程式中的段錯誤?
有個網友對這個做了比較全面的總結,除了感謝他外,我把位址弄了過來。
文章名字叫《段錯誤bug的除錯》
位址是:
應該說是很全面的。
而我常用的除錯方法有:
1)在程式內部的關鍵部位輸出(printf)資訊,那樣可以跟蹤 段錯誤 在**中可能的位置
為了方便使用這種除錯方法,可以用條件編譯指令#ifdef debug和#endif把printf函式給包含起來,編譯的時候加上-ddebug引數就可以檢視除錯資訊。反之,不加上該引數進行除錯就可以。
2)用gdb來除錯,在執行到段錯誤的地方,會自動停下來並顯示出錯的行和行號
這個應該是很常用的,如果需要用gdb除錯,記得在編譯的時候加上-g引數,用來顯示除錯資訊
對於這個,網友在《段錯誤bug的除錯》文章裡創造性的使用這樣的方法,使得我們在執行程式的時候就可以動態撲獲段錯誤可能出現的位置:
通過撲獲sigsegv訊號來觸發系統呼叫gdb來輸出除錯資訊。
如果加上上面提到的條件編譯,那我們就可以非常方便的進行段錯誤的除錯拉。
段錯誤總結
sigsegv是在訪問記憶體時發生的錯誤,它屬於記憶體管理的範疇 sigsegv是乙個使用者態的概念,是作業系統在使用者態程式錯誤訪問記憶體時所做出的處理。當使用者態程式訪問 訪問表示讀 寫或執行 不允許訪問的記憶體時,產生sigsegv。當使用者態程式以錯誤的方式訪問允許訪問的記憶體時,產生sig...
段錯誤?打的就是段錯誤!!
呵,段錯誤?自從我看了這篇文章,我還會怕你個小小段錯誤?請開啟你的linux終端,跟緊咯,準備發車!嘟嘟嘟噠 include void errfunc intmain 這段 拿去執行,肯定段錯誤。系統會在程式崩潰的那一剎那將整個核心的資訊記錄在乙個檔案裡邊。如果你是第一次,那麼ls是查不到的。這樣 ...
常見段錯誤
在linux記憶體管理中,linux結合了cpu架構採用了分段機制 分段就是將記憶體分成大小不同的段空間,將程序之間和程序內部不同資料段之間隔離起來 當程式記憶體的資料的訪問超出了系統所給這個程式資料段的範圍,系統就會給程序傳送乙個訊號sigsegv,程式將終止退出。所以,可以說段錯誤都是對記憶體操...