[英]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.