簡體   English   中英

刪除char指針時出現分段錯誤

[英]Segmentation Fault in deleting char pointer

我在這里發布兩個片段。 第一個是在分配內存時給我Segmentation Fault。 第二個工作正常。

1)

int main()
{
  char* ch = new char;
  ch = "hello";
  cout << "\n " << ch << endl;
  delete[] ch;  ////OR delete ch; ---> have tried both
  return 0;
}

2)

int main()
{
  char* ch = new char;
  cin >> ch;
  cout << "\n " << ch << endl;
  delete[] ch;   ///OR delete ch /// Both are working fine....
  return 0;
}

誰能告訴我為什么第一個失敗並出現Segmentation Fault而第二個失敗時使用deletedelete[] 因為對我來說,這兩個程序似乎相同。

new char生成正好1個字符(不是1個字符的數組,請使用new char[1]

因此delete []不適用

在第一個示例中,您使用指向字符串“ hello”的指針覆蓋了指向已分配的1個字符的指針-刪除此字符串(因為它是靜態內存)將導致sesgfault

編輯

int main()
{
    char* ch = new char; // ch points to 1 character in dynamic memory
    ch = "hello";        // overwrite ch with pointer to static memory "hello"
    cout<<"\n "<<ch<<endl; // outputs the content of the static memory
    delete[] ch;         // tries to delete static memory
    return 0;
}

這兩個示例都存在問題:

  char* ch = new char;`
  ch = "hello";`    

new函數返回一個指向動態分配內存的地址。 您必須保存此返回值,以便以后可以發布delete 上面的代碼用“ hello”(字符串字面量)覆蓋此值。 您現在已經丟失了該值,因此無法使用適當的值調用delete

第二個示例,即使您說“工作正常”仍然是錯誤的。

  char* ch = new char;`    
  delete[] ch;   ///OR delete ch /// Both are working fine....`    

使用了錯誤的delete形式。 您分配了new ,因此必須使用delete而不是delete[]取消分配。 它是這樣工作的: new > deletenew[] -> delete[]

與大多數其他語言不同,如果您違反C ++規則,損壞的內存,覆蓋緩沖區等,則無法保證程序會崩潰,出現段錯誤等,以使您知道自己做錯了什么。

在這種情況下,您很幸運,使用錯誤形式的delete不會影響諸如char*類的簡單類型。 但是您不能保證如果您更改編譯器,運行時設置等,它將始終有效。

在第一個中,您將指針更改為指向字符串文字:

ch = "hello";

字符串文字是靜態數組,因此不能刪除。

第二個錯誤至少有兩個原因:

  • 您分配一個字符,而不是數組; 單個字符將被刪除,而delete不是delete[]
  • cin>>ch將(很可能)讀取多個字符,但是您僅為一個字符分配了空間。

這兩種情況都會導致不確定的行為,這可能會表現為可見錯誤,或者看起來似乎“工作正常”,但在您最不期望的情況下可能會失敗。

要分配數組,請使用new char[SIZE] ; 但是即使如此,您仍不能阻止用戶提供過多的輸入並溢出緩沖區。

除非您正在教自己如何處理原始內存(這是一門黑手藝,除非絕對必要,否則最好避免這樣做),否則您應該堅持為您管理內存的高級類型:

std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';

每種方法都有兩個問題,即嘗試分配字符數組時僅分配一個字符。

在第一個示例中,您還分配了一個字符,然后將指針重新分配給字符數組ch = "hello" 不會復制字符串,只是重新分配指針。 然后,您對delete []的調用將嘗試刪除未分配堆的字符串,因此出現段錯誤。 而且,您還會泄漏您分配的字符。

這兩個片段都出了什么問題:

第一個片段:

char* ch = new char; ch = "hello";

將字符串常量分配給非const char指針是不合法的。 另外,您在調用new之后立即重新分配指針。 現在, new返回的原始值將永遠丟失,並且在程序執行期間無法釋放。 這被稱為內存泄漏。

delete[] ch;

您嘗試取消分配字符串文字。 這會使您的程序崩潰。 只允許deletenew獲得的指針和從new[]獲得的delete[]指針。 刪除其他任何內容都有不確定的行為。

第二段:

cout<<"\n "<<ch<<endl;

ch指向單個字符,而不是以零結尾的char 數組 將此指針傳遞給cout具有不確定的行為。 您應該使用cout << *ch; 打印該單個字符或確保ch指向以零結尾的字符數組。

delete[] ch;

您使用new分配,必須使用delete取消分配。 在此處使用delete[]具有未定義的行為。

兩者都工作正常。

就像運行時錯誤一樣,“運行良好”是未定義行為的可能結果。

要回答這個問題,兩個片段都不正確。 第一個因為您很幸運而崩潰,第二個似乎因為您不幸運而工作了。

解決方案:使用std::string

您的程序中有幾個錯誤。

在第一個程序中,您不是刪除動態分配的內容,而是刪除靜態分配的字符串“ hello”。 實際上,當您執行ch =“ hello”時,您並沒有在錯誤分配的緩沖區“ new char”中復制字符串(此new只會分配一個char,而不是您要查找的字符),而是使指針ch指向起點位於不可寫內存中某處的字符串“ hello”(通常該字符串直接指向可執行文件)。 因此,刪除操作正在嘗試取消分配無法取消分配的內容。 因此,第一個程序可以像這樣重寫:

int main()
{
  const char* ch = "hello";
  cout<<"\n "<<ch<<endl;
  return 0;
}

或喜歡

int main()
{
  char* ch = new char[strlen("hello")+1];
  strcpy( ch, "hello");
  cout<<"\n "<<ch<<endl;
  delete[] ch;  // with square brackets, it's an array
  return 0;
}

您應該使用類似:

char * ch =新的char [6];

strcpy(ch,“ hello”);

...

delete [] ch;

暫無
暫無

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

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