2014-08-29 58 views
-1

我在這裏發佈兩個片段。 第一個是給我分配內存的分段錯誤。第二個工作正常。刪除字符指針的分段錯誤

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; 
} 

有誰請告訴我,爲什麼第一個與分段故障失敗,第二個是工作的罰款既deletedelete[]。因爲對我來說這兩個程序似乎都是一樣的。

+6

這是C++。使用'std :: string'。 'ch'只是一個指針。分配字符串文字只是使其指向字符串文字,並且剛分配的內存將丟失。第二個是未定義的行爲,如果你使用'delete []'而不是'delete'。出現工作正常≠工作正常。 – chris 2014-08-29 14:06:28

回答

2

new char產生恰好1個字符(未1個字符的陣列,使用new char[1]爲該)

所以刪除[]不會在第一示例應用

,則覆寫指針到您的分配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; 
} 
+0

但刪除也失敗..請參閱註釋////或刪除ch; --->已經試過 – user3990393 2014-08-29 14:06:47

+0

你正在刪除靜態內存,這就是爲什麼它是失敗的 – BeyelerStudios 2014-08-29 14:08:38

0

您應該使用類似於:

char * ch = new char [6];

strcpy(ch,「hello」);

...

delete [] ch;

+1

只有新的字符[5]不夠大,「你好」(6個字符,包括空終止符) – BeyelerStudios 2014-08-29 14:07:16

+0

你是對的我不算好! – Carles 2014-08-29 14:08:01

+0

我也可以使用第二個程序..我的問題是,爲什麼這是失敗..第二個是使用刪除和刪除[]都... – user3990393 2014-08-29 14:09:13

1

在第一個,你改變指針指向一個字符串:

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'; 
+0

但刪除[]也是工作文件沒有在第二個程序中失敗..那是什麼? – user3990393 2014-08-29 14:11:41

+3

好運。或者不是,取決於隱藏的bug何時會突然炸燬。 – Quentin 2014-08-29 14:13:10

+2

@ user3990393:如果您不幸,未定義的行爲可能會*顯示爲「正常工作」。但它可能隨時停止工作(如果您更改編譯器,或更改代碼或無明顯原因);你不能依賴它明顯的好行爲。 – 2014-08-29 14:14:01

1

每個問題都有幾個問題,即當您嘗試分配字符數組時,您只分配一個字符。

在第一個例子,你還分配單個字符,並隨後重新分配指針字符數組 - ch = "hello"複製字符串,只是重新分配的指針。您刪除[]的呼叫將嘗試刪除不是堆分配的字符串,因此會導致seg故障。而且你也泄漏了你分配的字符。

1

這裏是什麼地方錯了兩個片段:

第一個片段:

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

這是不合法的分配字符串文本到非const字符指針。 此外,您在撥打new後立即重新分配指針。由new返回的原始值現在永遠丟失,並且在程序期間不能自由。這被稱爲內存泄漏。

delete[] ch; 

您嘗試解除分配字符串文字。這會導致程序崩潰。你只能得到delete指針,你從newdelete[]得到的指針可以從new[]得到。刪除其他任何內容都有未定義的行爲。

第二片段:

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

ch點到單個字符,而不是零封端的炭陣列。將此指針傳遞給cout具有未定義的行爲。您應該使用cout << *ch;來打印該單個字符或確保ch指向零終止的字符數組。

delete[] ch; 

你跟new分配的,必須用delete解除分配。使用delete[]這裏有未定義的行爲。

兩者都工作正常....

「做工精細」是未定義行爲的一個可能的結果,就像一個運行時錯誤。

要回答這個問題,這兩個代碼段都不正確。第一個因爲幸運而崩潰,第二個因爲運氣不好而出現工作。

解決方法:使用std::string

1

你的程序有幾個錯誤。

在第一個程序中,您並未刪除動態分配的內容,而是靜態分配的字符串「hello」。事實上,當你執行ch =「hello」時,你並沒有在錯誤分配的緩衝區「new char」中拷貝字符串(這個新的字符只是分配一個字符,而不是你正在尋找的字符),但是你可以讓指針指向開始的字符串「hello」位於非可寫內存中的某處(通常該字符串直接指向可執行文件)。所以刪除操作試圖釋放一些無法釋放的東西。因此,第一個節目culd被改寫,如:

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; 
} 
2

沒有與這兩個例子中的問題:

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++,導致內存破壞規則,覆蓋緩衝,等等,有沒有保證你的程序會崩潰,賽格故障等,讓你知道,你做錯了什麼。

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