常見錯誤0xCCCCCCCCC 讀取字符串的字符時出錯及其引申。


問題描述
在一個函數調用中,使用二級指針作為函數參數,傳遞一個字符串指針數組,但是在訪問的時候,卻出現了運行時錯誤,具體表現為“0xCCCCCCCC 讀取字符串的字符時出錯”。

第一反應是字符串忘記初始化了,但是一檢查不對,我初始化了啊。怎么會出現這種問題,然后通過單步調試發現是傳值的二級指針指向的指針數組訪問越界了,代碼片段如下——

 

while ((string = *strings++) != NULL) {

while (*string != '\0') {
if (*string++ == ‘a’)//出錯的地方,此處string = 0xcccccccc,讀取字符串字符時錯誤
...
}
}


VS認為越界的字符串指針元素是未初始化的,所以會執行一個默認的初始化,在執行*strings++ 循環判定的時候,越界的元素內容為0xcccccccc,而不是NULL ,所以判斷語句無效,訪問了無法訪問的內存。

那么在判斷的時候,數組的邊界應該以數組元素的數量為界,而不是NULL 值。

相關知識點的補充:
0xcccccccc : Used by Microsoft’s C++ debugging runtime library to mark uninitialised stack memory
0xcdcdcdcd : Used by Microsoft’s C++ debugging runtime library to mark uninitialised heap memory
0xfeeefeee : Used by Microsoft’s HeapFree() to mark freed heap memory

對於0xcccccccc和0xcdcdcdcd,在 Debug 模式下,VC 會把未初始化的棧內存上的指針全部填成 0xcccccccc ,當字符串看就是 “燙燙燙燙……”。會把未初始化的堆內存上的指針全部填成 0xcdcdcdcd,當字符串看就是 “屯屯屯屯……”。

那么調試器為什么要這么做呢?VC的DEBUG版會把未初始化的指針自動初始化為0xcccccccc或0xcdcdcdcd,而不是就讓取隨機值,那是為了方便我們調試程序,如果野指針的初值不確定,那么每次調試同一個程序就可能出現不一樣的結果,比如這次程序崩掉,下次卻能正常運行,這樣顯然對我們解bug是非常不利的,所以自動初始化的目的是為了讓我們一眼就能確定我們使用了未初始化的野指針了(其實我還是覺得初始化為NULL比較痛快)。

對於0xfeeefeee,是用來標記堆上已經釋放掉的內存。注意,如果指針指向的內存被釋放了,變量變量本身的地址如未做改動,還是之前指向的內存的地址。如果該指針是一個類的指針,並且類中包含有指針變量,則內存被釋放后(對於C++類,通常是執行delete操作),類中的指針變量就會被賦值為0xfeeefeee。如果早調試代碼過程中,發現有值為0xfeeefeee的指針,就說明對應的內存被釋放掉了,我們的代碼已經出問題了。

這是VS特有的機制,在其他編譯器上可能會把指針初始化為NULL。

個代碼本身沒有問題,問題在於,我在主函數中進行操作時,忘了進行初始化就直接進行操作了。下面是錯誤代碼。定義了三個鏈表,未進行初始化就對其進行創建操作,導致報錯。

void main() {
LinkList LA, LB, LC;
CreatList(LA, A);
CreatList(LB, B);
CreatList(LC, C);
cout << "線性表A為:" << endl;
VisitList(LA);
cout << "線性表B為:" << endl;
VisitList(LB);
cout << "線性表C為:" << endl;
VisitList(LC);

}
解決方案
定義完成要進行初始化:

void main() {

LinkList LA, LB, LC;
InitList(LA);
CreatList(LA, A);
InitList(LB);
CreatList(LB, B);
InitList(LC);
CreatList(LC, C);
cout << "線性表A為:" << endl;
VisitList(LA);
cout << "線性表B為:" << endl;
VisitList(LB);
cout << "線性表C為:" << endl;
VisitList(LC);

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM