GCC編譯器段內存錯誤問題

就自己打碼的經驗來看,在linux的gcc編譯器中使用指針的時候,常常會出現段內存(segmentation fault)錯誤問題,我在寫課後習題的時候就出現了這麼一個問題。題目是要求處理4維矩陣(也就是一個二維數組啦)。

這是在用gdb調試的時候,出現的結果。重點在第一行。

將一個4維矩陣(matrix)傳入參數**p中,結果在函數首次用到*(*(p+i)+j)的時候就出錯了,但編譯可以通過,只不過出現warning。

但在VC6.0下直接報錯。連warning都不給。

如果把**p改爲(*p)[4],也就是把類型改爲指向一維數組的指針的時候,程序就可以正常運行。

在VC6.0下也可以通過。

看了習題答案,發現答案的函數參數直接用指針

不過爲什麼用2維數組就出錯了呢?

原因是2維數組,在表達式上可以解讀成指向一維數組的指針,2維數組在內存上是連續的,而數組名在表達式上可以解讀成一個常指針,指向2位數組的第一個元素。

說到底2位數組還是指針(解讀成),而不是指針的指針。因此他可以傳值給指針,但在傳給指針的指針的是時候,傳過去的仍然是初始元素的地址,即p是初始元素的地址,*p是初始元素的值,**p呢?什麼也不是,其值是不可預測的,因此linux系統就給了個segmentation fault。

 

值得注意的還有,在很多C語言的書中都有這麼一句,在很多情況下,數組名可以看成指針;這句話並不總是對的,亂搞的話會出現還是會有段內存錯誤問題。

首先,指針可以對其值進行操作,如p++,p--,p=array等等;但是數組不行,否則會報錯。

另外,當指針指向一個字符串常量,數組是字符數組時,若分別對其所指的值(對本身不會)進行修改,指針會報錯,數組不會。

圖中strcpy對指針指向的字符串進行修改。

例如這樣,會報錯。字符數組就不用說了,當然可以通過。咱們經常這麼幹。

只修改一個也不行。仍然報錯(segmentation fault)

所以,如果你要寫一個字符串數組,並且要對它進行操作的話,寫成*p[ n ],也就是數組指針,讓每個指針指向一個字符串常量,以此達到節省內存的目的是不太合理的。

另外一個常見的段內存錯誤是沒有給指針賦值就改變它的值。

經常,我們用一個指針來當中間變量的時候常常忘了給他初始化,

結果只能是意料之中。

另外如果用NULL來初始化呢?那更加不行了,上面講到NULL是程序的禁區,修改了他,同樣會出現段內存錯誤。

 

總結一下,出現段內存錯誤(segmentation fault(core dumped))有一下原因:

1、使用一個地址不明的指針;例如指針的值是一個int類型的變量;int *p;int a; p = a;

2、修改指向字符串常量的指針;char *p = “AC OCEAN”;*(p+1) = 'A';    

    這裏應該注意:這樣寫是合法的: char *p1 = “I love you”,char *p2 = “I beat you”,p1 = p2;

3、修改指向null的指針的所指值。

4、修改沒有初始化的指針的所指值。

 

另外:數組名不一定總是等價於指針;

        指向數組的指針不是指針的指針;

        使用指針數組來操作字符串常量有可能弄巧成拙;

 

最後,編譯器是不會對數組越界做檢測的。如果越界,在unix或linux下會報段內存錯誤,在其他操作系統下會破壞其他內存或直接不給通過編譯。unix下出現段內存錯誤會生成core文件,方便用gdb來調試。但是我在unbuntu17.10下報核心轉儲的時候沒有生成core文件/(ㄒoㄒ)/~~。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章