程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 你的C/C++程序為什麼無法運行?揭秘Segmentation fault

你的C/C++程序為什麼無法運行?揭秘Segmentation fault

編輯:C++入門知識

你的C/C++程序為什麼無法運行?揭秘Segmentation fault


 

 

追溯段錯誤

如果你覺得你已經理解了段錯誤的根源,也知道了如何防止段錯誤,那麼可以到此為止。否則,下面的內容或許對你有所啟發。

malloc

我們開始為指針所指向的地址分配內存:
這裡寫圖片描述vcc8c3Ryb25nPrbOtO3O8zwvc3Ryb25nPrXEx7DPpjo8L3A+DQo8cD48aW1nIGFsdD0="這裡寫圖片描述" src="http://www.bkjia.com/uploads/allimg/150504/045T33G3-1.png" title="\" />

上面的圖告訴我們一些信息:

紅線勾勒出的內容是:
從函數func1的局部變量中取出指針dest(char ** 型)指向的地址,正確的代碼中地址是0x7fffffffddc0,而錯誤的代碼中地址則是0x0.

下一步即將執行黃線勾勒出的內容

/*
 注意這裡的rax在錯誤的代碼中為0x0
 而rdx的值為malloc出的內存地址0x602010
*/
mov    QWORD PTR [rax],rdx

那麼,當執行上面的代碼時,錯誤的代碼試圖將malloc分配出的在堆上的內存地址當作值放在指針dest指向的地址中。

地址:0x0 值:0x602010

那麼就出現了上篇所說的,0x0是不能被訪問的地址,也就不可能完成賦值操作。所以就會出現段錯誤
這裡寫圖片描述

什麼是段錯誤

對於很多人來講。上面的分析比第一篇要深入一些,也許看得到真相前的每一步才能讓人踏實。

現在,我們來看看什麼是段錯誤。

下圖是一個進程地址空間的描述,這是一個舊圖,網上到處都是,但可以用來理解VMA:
這裡寫圖片描述

上面這幅圖會告訴我們什麼呢?

內核虛擬內存空間,你肯定訪問不了.
用戶棧,用戶進程啟動就會有這樣一個結構,你超過它的上界就到了內核虛擬內存空間,就會出現段錯誤.
內存映射mmp區域.
堆,malloc、calloc就在這裡找地址分配.(事實上不僅如此)
代碼、數據段 包括全局變量、靜態變量、代碼、數據等等.

如果你訪問了內核虛擬內存空間(就是比ebp大的空間,1都不行)、代碼段、數據段都會引發段錯誤。

在上篇的例子中,是由於訪問了圖中紅色圈出的保留區域造成的段錯誤

補充一下x86_64的VMA-layout:

這裡寫圖片描述

找到代碼中的段錯誤

方法有很多。我也只會1個,畢竟我不寫C/C++,更不是這方面的老手。
利用coredump+gdb來做。
獲取coredump的方法:

1.在shell中`ulimit -c unlimited`
2.運行你發生了段錯誤的程序

有了coredump,就可以拿gdb來掰掰了gdb xx xxcoredump.
這裡寫圖片描述
上圖有幾個信息:

1.signal 11,是什麼呢?
這裡寫圖片描述
2.Segmentation fualt 段錯誤
3.stack2.c中的第8行出現錯誤.
4.細心觀察還會看到函數func1的參數dest=0x0.

我想,對於這樣一個簡單的c程序,上面的信息足夠了.
這裡寫圖片描述

其它

也許後面還想看看mmap、mm的fault處理、頁異常處理還有signal的一些東西.
但本篇,就此結束.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved