2014-07-07 196 views
1

我試圖搜索相同的問題,但沒有人幫助我。當我運行程序時,出現「發生緩衝區溢出......」錯誤。緩衝區溢出刪除[]

構造方法:

Player(char* n) 
{ 
    length = strlen(n); 
    name = new char[length+1]; 

    for(unsigned int i(0); i < length; i++) 
     name[i] = n[i]; 

    name[length] = '\0'; 
} 

Destr:

~Player(void) 
{ 
    delete [] name; 
} 

我NULL結尾的字符串,並沒有得到出界,是什麼問題?

+4

該類是否遵循[Rule of Three](http://stackoverflow.com/questions/4172722)?如果沒有,那麼你很可能會刪除兩次相同的緩衝區。使用'的std :: string'正確地管理動態內存給你,除非你特別想練習指針雜耍技能。 –

+2

你怎麼知道它是引起問題這個特殊的代碼? – Jon

+0

相關:[五規則(http://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11) – Deduplicator

回答

1

在你發佈的代碼中沒有明顯的錯誤,但試圖通過處理原始指針來管理動態內存將幾乎不可避免地導致類似的錯誤。

也許您沒有正確實施或刪除複製構造函數和複製賦值運算符,根據Rule of Three。在這種情況下,複製一個Player對象將給兩個指向同一數組的指針的對象;他們都會嘗試刪除該數組,給出未定義的行爲。

最簡單的解決方案是使用專爲管理字符串設計的類來管理字符串。改變name類型std::string,然後構造函數可以簡單地像

explicit Player(std::string const & n) : name(n) {} 

而且也沒有必要聲明析構函數(或移動/拷貝構造函數/賦值運算符)在所有。

0

因此...已經提供了使用std::string的解決方案,但讓我給出另一種解決方案,保持您的成員變量不變。

問題是這樣的。假設你有這樣的代碼的地方:

Player p1("Bob"); // Okay 
Player p2("Annie"); // Okay 
p2 = p1; // Oops! (1) 
Player p3(p1); // Oops! (2) 

在(1),該方法Player& Player::operator=(const Player&)被調用。既然你沒有提供,編譯器會爲你生成一個。當它這樣做時,它只是假定它可以複製所有成員變量。在這種情況下,它複製了Player::namePlayer::length。所以,我們有p1.name == p2.name。現在調用p2的析構函數時,將刪除p2.name指向的已分配內存。然後當調用p1的析構函數時,相同的內存將被刪除(因爲p1.name == p2.name)!這是違法的。

要解決這個問題,你可以自己寫一個賦值操作符。 (2),發生同樣的問題。您沒有複製構造函數,因此編譯器會爲您生成一個。它也會假設它可以複製所有的成員變量,所以當析構函數被調用時,它們會嘗試再次刪除相同的內存。爲了解決這個問題,也寫了拷貝構造函數:

Player::Player(const Player& other) 
{ 
    if (this == &other) return; 
    length = other.length; 
    name = new char[length + 1]; 
    for (unsigned int i = 0; i < length; ++i) name[i] = other.name[i]; 
} 

在這一天結束時,你應該使用雖然一個std::string

+0

謝謝!我太接近了這個問題,但是這個曲子讀到它10分鐘前我沒有做;)突然發現,我沒有用「刪除[]」一個錯誤。對於不正確的問題,我很抱歉,但這些答案解決了我不知道的問題。再次感謝! – pushandpop

+0

這不是實現複製語義的最好的例子。特別是,不調用析構函數 - ,讓未定義行爲(即使你可能會擺脫它在這裏)。我希望有合理的例外安全;如果內存分配失敗,這會使分配目標留下一個懸掛指針。考慮[copy-and-swap idiom](http://stackoverflow.com/questions/3279543)使用複製構造函數進行安全賦值,而不是手動編寫這兩個函數。因爲您正在初始化一個新對象,所以不需要在構造函數中檢查相同的對象。 –