程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C失路指針詳解

C失路指針詳解

編輯:關於C++

C失路指針詳解。本站提示廣大學習愛好者:(C失路指針詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C失路指針詳解正文


本文較為詳實的講述了C說話的失路指針,剖析了其概念、道理與檢測辦法。分享給年夜家供年夜家參考。詳細以下:

普通來講,在盤算機編程范疇中,失路指針,或稱懸空指針、野指針,指的是不指向任何正當的對象的指針。

當所指向的對象被釋放或許發出,然則對該指針沒有作任何的修正,以致於該指針仍然指向曾經收受接管的內存地址,此情形下該指針便稱失路指針。若操作體系將這部門曾經釋放的內存從新分派給別的一個過程,而本來的法式從新援用如今的失路指針,則將發生沒法預感的效果。由於此時失路指針所指向的內存如今包括的曾經完整是分歧的數據。平日來講,若本來的法式持續往失路指針所指向的內存地址寫入數據,這些和本來法式不相干的數據將被破壞,進而招致弗成預感的法式毛病。這類類型的法式毛病,不輕易找到成績的緣由,平日會招致段毛病(Linux體系中)和普通掩護毛病(Windows體系中)。假如操作體系的內存分派器將曾經被籠罩的數據區域再分派,便可能會影響體系的穩固性。

某些編程說話許可未初始化的指針的存在,而這類指針即為野指針。野指針所招致的毛病和失路指針異常類似,但野指針的成績更輕易被發明。

失路指針的成因

在許多編程說話中(如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 如今釀成了一個懸空指針 */
  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 內存分派器,它虛擬清除了相似其它內存毛病(不正當或許兩次釋放內存)的失路指針毛病。

還有一種方法是貝姆渣滓搜集器,一種守舊的渣滓收受接管辦法,可以或許替換C和C++中尺度內存分派函數。這類辦法完整清除了失路指針的毛病,經由過程去除內存釋放的函數代之以渣滓收受接管器完成對象的收受接管。

像Java說話,失路指針如許的毛病是不會產生的,由於Java中沒有明白地從新分派內存的機制。並且渣滓收受接管器只會在對象的援用數為零時從新分派內存。

失路指針的檢測

為了能發明失路指針,一種廣泛的編程技巧——一旦指針指向的內存空間被釋放,就立刻把該指針置為空指針或許為一個不法的地址。當空指針被從新援用時,此時法式將會立刻停滯,這將防止數據破壞或許某些沒法預感的效果。這將使接上去的編程進程發生的毛病變得輕易發明息爭決了。這類技巧在該指針有多個復制時就沒法起到應有的感化了。

一些調試器會主動地用特定的形式來籠罩曾經釋放的數據,如0xDEADBEEF (Microsoft's Visual C/C++ 調試器,例如,依據哪一種類型被釋放采取 0xCC,0xCD 或許 0xDD)。這類辦法經由過程將數據無用化,來避免曾經釋放的數據從新被應用。這類辦法的感化長短常明顯的 (該形式可以贊助法式來辨別哪些內存是方才釋放的)。

某些對象,如Valgrind, Mudflap或許 LLVM可以用來檢測失路指針的應用。

總的來講,失路指針對C法式平安性影響偉大,是C法式員必需謹嚴處置的一個成績。信任本文所述對年夜家C法式設計有必定的自創價值。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved