[英]Buffer Overrun with delete []
我嘗試搜索相同的問題,但沒有一個人幫助我。 運行程序時,出現“發生緩沖區溢出...”錯誤。
構造方法:
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終止的字符串,並且沒有超出范圍,這是什么問題?
您發布的代碼中沒有明顯的錯誤,但是嘗試通過處理原始指針來管理動態內存幾乎不可避免地會導致此類錯誤。
也許您沒有按照“三法則”正確實現或刪除復制構造函數和復制分配運算符。 在這種情況下,復制Player
對象將為兩個對象提供指向同一數組的指針; 他們兩個都將嘗試刪除該數組,從而產生不確定的行為。
最簡單的解決方案是使用用於管理字符串的類來管理您的字符串。 將name
的類型更改為std::string
,然后構造函數就可以像
explicit Player(std::string const & n) : name(n) {}
而且根本不需要聲明析構函數(或移動/復制構造函數/賦值運算符)。
所以...提供了一個使用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::name
和Player::length
。 因此,我們有p1.name == p2.name
。 現在,當調用p2
的析構函數時,將刪除由p2.name
指向的已分配內存。 然后,當調用p1
的析構函數時,將刪除相同的內存(因為p1.name == p2.name
)! 那是非法的。
要解決此問題,您可以自己編寫一個賦值運算符。
Player& Player::operator = (const Player& other)
{
// Are we the same object?
if (this == &other) return *this;
// Delete the memory. So call the destructor.
this->~Player();
// Make room for the new name.
length = other.length;
name = new char[length + 1];
// Copy it over.
for (unsigned int i = 0; i < length; ++i) name[i] = other.name[i];
name[length] = '\0';
// All done!
return *this;
}
在(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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.