C迷途指標詳解_C 語言

來源:互聯網
上載者:User

本文較為詳盡的講述了C語言的迷途指標,分析了其概念、原理與檢測方法。分享給大家供大家參考。具體如下:

一般來說,在電腦編程領域中,迷途指標,或稱懸null 指標、野指標,指的是不指向任何合法的對象的指標。

當所指向的對象被釋放或者收回,但是對該指標沒有作任何的修改,以至於該指標仍舊指向已經回收的記憶體位址,此情況下該指標便稱迷途指標。若作業系統將這部分已經釋放的記憶體重新分配給另外一個進程,而原來的程式重新引用現在的迷途指標,則將產生無法預料的後果。因為此時迷途指標所指向的記憶體現在包含的已經完全是不同的資料。通常來說,若原來的程式繼續往迷途指標所指向的記憶體位址寫入資料,這些和原來程式不相關的資料將被損壞,進而導致不可預料的程式錯誤。這種類型的程式錯誤,不容易找到問題的原因,通常會導致段錯誤(Linux系統中)和一般保護錯誤(Windows系統中)。如果作業系統的記憶體 Clerk將已經被覆蓋的資料區域再分配,就可能會影響系統的穩定性。

某些程式設計語言允許未初始化的指標的存在,而這類指標即為野指標。野指標所導致的錯誤和迷途指標非常相似,但野指標的問題更容易被發現。

迷途指標的成因

在很多程式設計語言中(如C語言)從記憶體中刪除一個對象或者返回時刪除棧幀後,並不會改變相關的指標的值。該指標仍然指向原來的記憶體位址,即使引用已經刪除,現在也可能已經被其它進程使用了。

一個直接的例子,如下所示:

{  char *cp = NULL;  /* ... */  {    char c;    cp = &c;  } /* c falls out of scope */        /* cp is now a dangling pointer */}

上述問題的解決方案是在該部分程式退出之前立即給CP賦0值(NULL)。另一個辦法是保證CP在沒有初始化之前,將不再被使用。

迷途指標經常出現在混雜使用malloc() 和 free() 庫調用: 當指標指向的記憶體釋放了,這時該指標就是迷途的。和前面的例子一樣,一個避免這個錯誤的方法是在釋放它的引用後將該指標的值重設為NULL,如下所示:

#include <stdlib.h>{  char *cp = malloc ( A_CONST );  /* ... */  free ( cp );   /* cp 現在變成了一個懸null 指標 */  cp = NULL;    /* cp 現在不是懸空了 */  /* ... */}

有個常見的錯誤是當返回一個基於棧分配的局部變數的地址時,一旦調用的函數返回,分配給這些變數的空間將被回收,此時它們擁有的是"垃圾值"。

int * func ( void ){  int num = 1234;  /* ... */  return #}

在調用func之後一段時間,嘗試從該指標中讀取num的值,可能仍然能夠返回正確的值(1234),但是任何接下來的函數調用會覆蓋原來的棧為num分配的空間。這時,再從該指標讀取num的值就不正確了。如果要使一個指向num的指標都返回正確的num值,則需要將該變數聲明為static。

野指標的產生

野指標指的是還沒有初始化的指標。嚴格地說,程式設計語言中每個指標在初始化前都是野指標。

一般於未初始化時便使用指標就會產生問題。大多數的編譯器都能檢測到這一問題並警告使用者。

int f(int i){  char* cp;  //cp 是野指標  static char* scp; //scp 不是野指標,靜態變數自動初始化為0並保留它們的值//使用這種特徵可能被認為壞的編程風格}

迷途指標導致的安全性漏洞

如同緩衝溢出錯誤,迷途指標/野指標這類錯誤經常會導致安全性漏洞。 例如,如果一個指標用來調用一個虛函數,由於vtable指標被覆蓋了,因此可能會訪問一個不同的地址(指向被利用的代碼)。或者,如果該指標用來寫入記憶體,其它的資料結構就有可能損壞了。一旦該指標成為迷途指標,即使這段記憶體是唯讀,仍然會導致資訊的泄露(如果感興趣的資料放在下一個資料結構裡面,恰好分配在這段記憶體之中)或者存取權限的增加(如果現在不可使用的記憶體恰恰被用來安全檢測).

避免迷途指標的錯誤

避免迷途指標,有一種受歡迎的方法——即使用智能指標(Smart pointer)。智能指標使用引用計數來回收對象。一些其它的技術包括tombstone法和locks-and-keys法。

另外,可以使用 DieHard 記憶體 Clerk,它虛擬消除了類似其它記憶體錯誤(不合法或者兩次釋放記憶體)的迷途指標錯誤。

還有一種辦法是貝姆垃圾收集器,一種保守的記憶體回收方法,能夠替代C和C++中標準記憶體配置函數。這種方法完全消除了迷途指標的錯誤,通過去除記憶體釋放的函數代之以記憶體回收行程完成對象的回收。

像Java語言,迷途指標這樣的錯誤是不會發生的,因為Java中沒有明確地重新分配記憶體的機制。而且記憶體回收行程只會在對象的引用數為零時重新分配記憶體。

迷途指標的檢測

為了能發現迷途指標,一種普遍的編程技術——一旦指標指向的記憶體空間被釋放,就立即把該指標置為空白指標或者為一個非法的地址。當null 指標被重新引用時,此時程式將會立即停止,這將避免資料損毀或者某些無法預料的後果。這將使接下來的編程過程產生的錯誤變得容易發現和解決了。這種技術在該指標有多個複製時就無法起到應有的作用了。

一些調試器會自動地用特定的模式來覆蓋已經釋放的資料,如0xDEADBEEF (Microsoft's Visual C/C++ 調試器,例如,根據哪種類型被釋放採用 0xCC,0xCD 或者 0xDD)。這種方法通過將資料無用化,來防止已經釋放的資料重新被使用。這種方法的作用是非常顯著的 (該模式可以協助程式來區分哪些記憶體是剛剛釋放的)。

某些工具,如Valgrind, Mudflap或者 LLVM可以用來檢測迷途指標的使用。

總的來說,迷途指標對C程式安全性影響巨大,是C程式員必須謹慎處理的一個問題。相信本文所述對大家C程式設計有一定的借鑒價值。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.