簡體   English   中英

重用懸空或 null 指針時出錯(分段錯誤)

[英]Error (Segmentation Fault) while reusing a dangling or null pointer

#include<stdlib.h>
#include<string.h>
int main ( void )
{
  char *title=NULL;
  title = (char *) malloc(15);
  strcpy(title, "C Programming");
  printf("String = %c", *title);
  free(title); 
//   title=NULL;    //or title = 0;
  strcpy(title, "C++");
  printf(" %s", title);
  return 0;
}

當我取消注釋“title=NULL”行時,程序因分段錯誤而崩潰; 有人可以解釋這種行為嗎

打印 "String = C C++" 否則

如果您的代碼取消引用懸空或 null 指針,則行為未定義- 任何事情都可能發生。 這兩種可能的行為(“它按預期工作”和“它崩潰”)實際上是未定義行為的最常見表現。

有時,您可以合理化未定義的行為 - 就像在這種情況下一樣。 但你不能總是指望它是可以理解的。

  • 如果您的代碼嘗試將內容寫入 null 地址,它會崩潰,因為操作系統可以檢測到這一點。 它非常簡單(空指針指向一個不可讀和不可寫的 memory 頁面)並且很有用(一個好的調試器會直接停在有問題的代碼行)。
  • 如果你的代碼試圖重用一個懸空指針,它指向的地址通常仍然是可寫的free不會告訴操作系統它現在是懸空的。 free只會編輯一些簿記數據結構,因此釋放的地址將可用於將來的分配。 訪問懸空指針不容易導致崩潰,因為操作系統只能在頁面粒度上管理 memory 訪問,可以是4 KiB或類似的大小。

90% 的問題是紅鯡魚 整個問題可以用一行來重申:

當我這樣做時:title=NULL; strcpy(標題,“C++”); 我的程序崩潰了。 為什么?

上面的代碼嘗試將字節寫入 null 指針引用的 memory 地址。 根據定義,這是未定義的行為。 未定義的行為意味着任何事情都可能發生,例如一碗矮牽牛花和抹香鯨可能會從天上掉下來,但在絕大多數執行環境中,當然在您的執行環境中,null 指針引用的 memory 地址不是可寫,因此這將始終導致您遇到的確切行為:分段錯誤。

此外,為了解決問題的其余部分,當將指針設置為 NULL 的行被注釋掉時,您正在寫入已釋放的 memory 位置。 由於它已被釋放,因此不應再次訪問它,並且再次訪問它是未定義的行為,只有在這種情況下,沒有檢測到濫用的機制,所以它只是巧合。 嘗試在不同的環境中運行相同的程序,就會有成盆的矮牽牛和抹香鯨從天而降。

這是未定義的行為。 您通過執行free(title)告訴操作系統您的程序不再需要 memory 但這並不意味着 memory 會立即從您的進程中取出。 Instead title still holds address of (now freed and not accounted for) memory and subsequent strcpy() (depending on OS and its memory usage policy) might be able to write into that memory and printf() will get address (again freed and unaccounted for) 並將打印字符,直到到達strcpy()放置的第一個\0

當您在釋放NULL title ,期望指向已分配 memory 的指針的其他函數(此處為strcpy() )將獲得無效輸入並失敗(出現分段錯誤)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM