[英]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而第二個失敗時使用delete
和delete[]
。 因為對我來說,這兩個程序似乎相同。
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
> delete
, new[]
-> 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;
您嘗試取消分配字符串文字。 這會使您的程序崩潰。 只允許delete
從new
獲得的指針和從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.