这是程序......
class CopyCon
{
public:
char *name;
CopyCon()
{
name = new char;
}
CopyCon(const CopyCon &objCopyCon)
{
name = new char;
_tcscpy(name,objCopyCon.name);
}
~CopyCon()
{
if( name != NULL )
{
delete name;
name = NULL;
}
}
};
int main()
{
CopyCon objCopyCon1;
objCopyCon1.name = "Hai";
CopyCon objCopyCon2(objCopyCon1);
objCopyCon1.name = "Hello";
cout<<objCopyCon2.name<<endl;
return 0;
}
一旦代码执行完成,当析构函数被调用时,它会在'delete'上崩溃说...
计划:......
HEAP CORRUPTION DETECTED:在正常块(#124)之后的0x00366990。 CRT检测到应用程序在堆缓冲区结束后写入内存。
(按“重试”调试应用程序)
我们不必在析构函数中清除堆内存。这个程序有什么问题?请帮忙! 复制构造函数按预期完美地工作。但还是......!?
答案 0 :(得分:5)
问题是你在复制构造函数中只分配了一个char
。
在main
中,您正在分配一个4字节的字符串(记住空值),但是当您复制该对象时,您只能为1个字节分配足够的空间。
您可能想要做的是改变
name = new char;
到
name = new char[tcslen(objCopyCon.name) + 1];
在析构函数中:
delete name;
到
delete [] name;
此外:
您正在将"Hai"
和"Hello"
分配给隐藏在构造函数中分配的内存的objCopyCon1.name
。 永远不会释放此内存!
答案 1 :(得分:4)
您写过已分配的变量,这是未定义的行为。
当下面的行开始时
CopyCon objCopyCon1;
objCopyCon1.name = "Hai";
CopyCon objCopyCon2(objCopyCon1);
_tcscpy()
将4个字符(3个字母和空终止符)复制到一个只能合法保存一个字符的缓冲区中。所以你写过缓冲区结束,这会导致堆损坏。
您需要分配正确大小的缓冲区:
CopyCon(const CopyCon &objCopyCon)
{
name = new char[_tcslen(objCopyCon.name) +1];
_tcscpy(name,objCopyCon.name);
}
您还需要将析构函数中的delete
更改为delete[]
,并将所有其他new
调用更改为new[]
以避免未定义的行为。
答案 2 :(得分:1)
您正在分配一个字符并尝试将多个字符复制到该内存位置。首先找出字符串的长度,然后使用length + 1
语法分配new char[length+1]
个字符(额外的char以容纳NULL字符)。您需要相应地将析构函数更改为delete[] name
。
答案 3 :(得分:1)
除了每个人提到的new char
问题外,字符串“Hai”和“Hello”都驻留在只读内存中。这意味着你不能删除它们(但是你在析构函数中这样做) - 这确实会导致崩溃。您的代码不应直接分配给name
,而是使用set函数,例如:
void set_name(const char *new_name)
{
delete [] name; // delete is a no-op on a NULL pointer
name = new char[tcslen(new_name) + 1];
_tcscpy(name,new_name);
}
我很惊讶,赋值不会产生编译器警告说实话。您正在为const char *
分配char *
,这可能导致各种问题,例如您所看到的问题。
答案 4 :(得分:0)
copy ctor
的工作应该是创建对象的副本。因此,两个对象中char
指向的name
数组应该是same size
和same content
,这在您的情况下不会发生。所以改变
name = new char; // allocates only one char
到
name = new char[strlen(objCopyCon.name) + 1]; // allocate array of char
答案 5 :(得分:0)
您需要分配足够的内存来保存您尝试存储的信息。 “Hai”是4个字节或字符(包括空终止符),并且您只分配了一个。您也不会使用“=”将字符串从一个内存位置复制到另一个内存位置。你需要跨越字符串。
使用std :: string它会让你的生活更轻松一百万次:)
答案 6 :(得分:0)
这里的代码完美无缺!
class CopyCon
{
public:
char *name;
CopyCon()
{
name = NULL;
}
CopyCon(const CopyCon &objCopyCon)
{
name = new char[_tcslen(objCopyCon.name)+1];
_tcscpy(name,objCopyCon.name);
}
~CopyCon()
{
if( name != NULL )
{
delete[] name;
name = NULL;
}
}
void set_name(const char *new_name)
{
//delete [] name; // delete is a no-op on a NULL pointer
if( NULL != name)
{
delete[] name; name = NULL;
}
name = new char[_tcslen(new_name) + 1];
_tcscpy(name,new_name);
}
};
int main()
{
CopyCon objCopyCon1;
objCopyCon1.set_name("Hai");
CopyCon objCopyCon2(objCopyCon1);
objCopyCon1.set_name("Hello");
cout<<objCopyCon1.name<<endl;
cout<<objCopyCon2.name<<endl;
return 0;
}
感谢所有观点。它确实有帮助!