野指針

野指針指指向一個已刪除的對象或未申請訪問受限內存區域的指針。與空指針不同,野指針無法通過簡單地判斷是否爲NULL避免,而只能通過養成良好的編程習慣來盡力減少。對野指針進行操作很容易造成程序錯誤。


成因

野指針主要是因爲這些疏忽而出現的:
指針變量未初始化


任何指針變量剛被創建時不會自動成爲NULL指針,它的缺省值是隨機的,它會亂指一氣。所以,指針變量在創建的同時應當被初始化,要麼將指針設置爲NULL,要麼讓它指向合法的內存。
指針釋放後之後未置空


有時指針在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,因爲任何指針變量剛被創建時不會自動成爲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操作符取釋放它。
發佈了18 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章