首先段錯誤產生的原因有兩個:
1、訪問的內存地址超出了系統給這個變量分配的內存空間(越界)
2、系統訪問了程序的靜態數據區
段錯誤產生的過程是:
1、用戶程序要訪問的一個虛擬地址(VA),經過MMU檢查後發現是無權訪問的
2、MMU產生一個異常,CPU從用戶態切換到特權模式,產生遺產關中斷,並跳轉到內核代碼中執行異常服務程序。
3、內核吧這個異常解釋Wie段錯誤,並把引發段錯誤的進程終止。
下面是自己遇到的例子:
1、我想通過二維指針訪問二維數組的時候,運行期間發生了段錯誤,也就是我訪問了不該訪問的內存空間,代碼如下
編譯出現報警:
運行後出現
原因分析:實質上通過ppArray = array之後,ppArray就是數組array[0][0]的地址了,那麼*ppArray就是array[0][0],值爲7,那麼如果我通過**ppArray操作,則訪問了地址爲7的空間,當然會出現段錯誤。
2、實質上可以直接用一級指針訪問二維數組。
通過這種方式會有警告:
3、我們可以把數組二維數組看爲一維數組內嵌套一維數組,用一級指針指向二維數組array[3][4]的行,代碼如下
4、如果必須要用二級指針訪問二維數組的話,可以藉助指針數組
另外一個常見的段錯誤的例子:
當指針訪問靜態區的時候會出現段錯誤
當前指針指向靜態區的數據"hello",而後我又通過指針往靜態區寫數據,訪問了我不該訪問的地址,必然出現段錯誤。
然而當我通過變量定義
unsigned char *a = "hello";
unsigned char *ptr = a;
ptr = "world";
不會出現段錯誤,因爲ptr = a實現了ptr指向"hello",而ptr本身是存在棧區的
段錯誤的分析辦法:
如左圖所示:
1、main函數壓棧,分配棧空間,創建變量*p,其中,p爲1000,也就是*p指向地址爲1000的內存空間
2、fun函數壓棧,分配棧空間,創建**變量,其中,*p爲2000,也就是**p指向地址爲2000的內存空間。
3、執行*p = string,而string = 5000,5000這塊地址存儲的是hello字符串,也就是**p指向存儲"hello"的地址
4、fun函數出棧,那麼main函數中的p=5000,也就是*p指向地址爲5000內存(存放的爲hello字符串)
5、程序執行完後應該free(p)
如左圖所示:
1、main函數壓棧,分配棧空間,創建變量*p,其中,p爲1000,也就是*p指向地址爲1000的內存空間
2、fun函數壓棧,分配棧空間,創建**變量,其中,*p爲2000,也就是**p指向地址爲2000的內存空間。
3、執行*p = string,而string = 5000,5000這塊地址存儲的是hello字符串,也就是**p指向存儲"hello"的地址
4、fun函數出棧,那麼main函數中的p=5000,也就是*p指向地址爲5000內存(存放的爲hello字符串)
5、程序執行完後應該free(p)