-
野指針
鎖定
野指針就是指針指向的位置是不可知的(隨機的、不正確的、沒有明確限制的)指針變量在定義時如果未初始化,其值是隨機的,指針變量的值是別的變量的地址,意味着指針指向了一個地址是不確定的變量,此時去解引用就是去訪問了一個不確定的地址,所以結果是不可知的。
- 中文名
- 野指針
- 外文名
- Wild Pointer
- 性 質
- 指針
- 領 域
- 編程
目錄
野指針成因
野指針指針變量未初始化
任何指針變量剛被創建時不會自動成為NULL指針,它的缺省值是隨機的,它會亂指一氣。所以,指針變量在創建的同時應當被初始化,要麼將指針設置為NULL,要麼讓它指向合法的內存。如果沒有初始化,編譯器會報錯“ ‘point’ may be uninitialized in the function ”。
野指針指針釋放後之後未置空
有時指針在free或delete後未賦值 NULL,便會使人以為是合法的。別看free和delete的名字(尤其是delete),它們只是把指針所指的內存給釋放掉,但並沒有把指針本身幹掉。此時指針指向的就是“垃圾”內存。釋放後的指針應立即將指針置為NULL,防止產生“野指針”。
野指針指針操作超越變量作用域
不要返回指向棧內存的指針或引用,因為棧內存在函數結束時會被釋放。示例程序如下:
class A { public: void Func(void){ cout << “Func of class A” << endl; } }; class B { public: A *p; void Test(void) { A a; p = &a; // 注意a的生命期 ,只在這個函數Test中,而不是整個class B } void Test1() { p->Func(); // p 是“野指針” } };
函數 Test1 在執行語句 p->Func時,p 的值還是 a 的地址,對象 a 的內容已經被清除,所以 p 就成了“野指針” 。
野指針規避
在養成這些習慣的情況下,野指針的危害是可以降低的:
野指針初始化時置 NULL
野指針釋放時置 NULL
當指針p指向的內存空間釋放時,沒有設置指針p的值為NULL。delete和free只是把內存空間釋放了,但是並沒有將指針p的值賦為NULL。通常判斷一個指針是否合法,都是使用if語句測試該指針是否為NULL。例如:
int *p=newint(6); delete p; // 應加入 p=NULL; 以防出錯 // ... if(p != NULL) { *p=7; cout << p << endl; }
對於使用 free 的情況,常常定義一個宏或者函數 xfree 來代替 free 置空指針:
#define xfree(x) free(x); x = NULL; // 在 C++ 中應使用 nullptr 指代空指針 // 一些平台上的 C/C++ 已經預先添加了 xfree 拓展,如 GNU 的 libiberty xfree(p); // 用函數實現,例如 GitHub 上的 AOSC-Dev/Anthon-Starter #9: static inline void *Xfree(void *ptr) { free(ptr); #ifdef __cplusplus return nullptr; #else return NULL; #endif } q=Xfree(q);
所以動態分配內存後,如果使用完這個動態分配的內存空間後,必須習慣性地使用delete操作符去釋放它。