內存篇之野指針

    前面兩文中內存錯誤釋放以及錯誤訪問指向棧的指針,從另外角度,其中一部分錯誤還可以歸結爲訪問了野指針。野指針又稱懸掛指針,代表那些指向不可用內存區域的指針。操作野指針,程序會發生難以預料的錯誤。形成野指針主要有以下原因:

1)指針沒有初始化。指針變量創建時不會自動指向null,其缺省值是隨機的,比如:

    int *p;

    *p = 0;

    這種代碼可能導致死機或者非法操作,所以使用指針前一定要初始化,使它指向分配好的可用空間,否則就成了野指針。

2)內存free後,指向內存的指針被誤當作合法指針而繼續使用。例如下例:

    char *p = (char *) malloc(100);

    strcpy(p, “hello”);

    free(p);          // p 所指的內存被釋放,但是p所指的地址仍然不變

    ……

    if(p != NULL)    // 沒有起到預防作用,因爲p值未變

    strcpy(p, “world”); // 出錯,訪問野指針

    初學者在釋放鏈表時也很容易犯類似錯誤:

    while (p)

    {

      free(p);

      q = p->next;    //p已釋放,p->next是訪問野指針

      p = q;

    }

    這裏代碼順序很敏感,上面的順序會導致野指針訪問,正確方法是:

    while (p)

    {

      q= p->next;

      delete p;

      p= q;

    }

    如果多個指針指向同一內存,這一問題也經常發生。free某個指針釋放了內存,其他指針即刻被懸掛成爲野指針,如果不注意而繼續訪問就會出錯。

3)指針指向失效的棧內存,比如:某子函數返回一指針,此指針指向子函數內部某局部變量,子函數退出後,該局部變量所在的棧內存就因自動出棧而釋放,而這個返回的指針也就成了野指針,不能再使用了。具體見下節例子。

    總之,野指針和正常指針都指向某塊內存,只是野指針所指的內存已不可用。就象一張失效的藏寶圖,寶藏如果不在,藏寶圖自然就成了廢紙一張。所謂的懸掛也是表達類似含義。另外要注意區分野指針和空指針概念:野指針不特指空指針,而是指向垃圾(不可用)內存的指針。可以用if(ptr==null)預防空指針,但對野指針不起作用。所以野指針比空指針更隱蔽,危害更大。

    思考下,內存重複free的錯誤是不是第二次free訪問了野指針?大家可以發表意見。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章