复制构造函数演示(崩溃...)

时间:2010-04-22 06:43:14

标签: c++ copy-constructor

这是程序......

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检测到应用程序在堆缓冲区结束后写入内存。

(按“重试”调试应用程序)

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

7 个答案:

答案 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 sizesame 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;
}

感谢所有观点。它确实有帮助!