0

这是程序...

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

一旦代码执行完成,当调用析构函数时,它会在“删除”时崩溃,说......

调试错误!

程序: ...

检测到堆损坏:在 0x00366990 的正常块 (#124) 之后。CRT 检测到应用程序在堆缓冲区结束后写入内存。

(按重试调试应用程序)

我们不必在析构函数中清除堆内存。这个程序有什么问题?请有人帮忙!复制构造函数按预期完美工作。但是还是……!?

4

7 回答 7

5

问题是您char在复制构造函数中只分配了一个。

main你分配一个 4 字节的字符串(记住 null),但是当你复制对象时,你只为 1 个字节分配了足够的空间。

你可能想做的是改变

name = new char;

name = new char[tcslen(objCopyCon.name) + 1];

在析构函数中:

delete name;

delete [] name;

还:

您正在分配"Hai"并且隐藏构造函数"Hello"objCopyCon1.name分配的内存。这段记忆永远无法释放!

于 2010-04-22T06:45:23.367 回答
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[]以避免未定义的行为。

于 2010-04-22T06:46:09.603 回答
1

您正在分配一个字符并尝试将多个字符复制到该内存位置。首先找出字符串的长度,然后使用语法分配length + 1字符(额外的字符以容纳 NULL 字符) 。new char[length+1]您需要相应地将您的析构函数更改为delete[] name.

于 2010-04-22T06:49:05.267 回答
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);
}

老实说,我很惊讶分配不会产生编译器警告。您正在将 a 分配const char *给 a char *,这可能会导致各种问题,例如您所看到的问题。

于 2010-04-22T07:03:09.117 回答
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;
}

感谢大家的观点。它真的有帮助!

于 2010-04-22T07:52:47.833 回答
0

的工作copy ctor应该是创建对象的副本。因此,两个对象中char指向的数组name应该是same sizeand same content,这在您的情况下不会发生。所以改变

name = new char; // allocates only one char

name = new char[strlen(objCopyCon.name) + 1]; // allocate array of char
于 2010-04-22T06:47:30.200 回答
0

您需要分配足够的内存来保存您尝试存储的信息。“Hai”是 4 个字节或字符(包括空终止符),您只分配了一个。您也不要使用“=”将字符串从一个内存位置复制到另一个内存位置。您需要对字符串进行strncpy。

使用 std::string 它会让你的生活轻松一百万倍:)

于 2010-04-22T06:48:15.783 回答