Копировать конструктор демо (сбой ...) - PullRequest
0 голосов
/ 22 апреля 2010

Вот программа ...

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

Когда выполнение кода завершается, когда вызывается деструктор, происходит сбой при удалении, говоря:

Ошибка отладки!

Программа: ...

ОБНАРУЖЕНА КОРРУПЦИЯ КАРТЫ: после блока Normal (# 124) в 0x00366990. CRT обнаружил, что приложение записало в память после завершения буфера кучи.

(Нажмите Retry для отладки приложения)

Разве нам не нужно очищать кучу памяти в деструкторе. Что не так с этой программой? Пожалуйста, помогите! Конструктор копирования работает отлично, как задумано. Но все же ...!?

Ответы [ 7 ]

5 голосов
/ 22 апреля 2010

Проблема в том, что вы выделяете только один char в конструкторе копирования.

В main вы назначаете 4-байтовую строку (запомните ноль), но когда вы копируете объект, вы выделяете достаточно места только для 1 байта.

Что вы, вероятно, хотите сделать, это изменить

name = new char;

до

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

А в деструкторе:

delete name;

до

delete [] name;

Также:

Вы присваиваете "Hai" и "Hello" objCopyCon1.name, которые скрывают память, выделенную в конструкторе. Эта память никогда не может быть освобождена!

4 голосов
/ 22 апреля 2010

Вы пишете после выделенной переменной, и это неопределенное поведение.

Когда следуют строки

 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[], чтобы избежать неопределенного поведения.

1 голос
/ 22 апреля 2010

Помимо проблемы new char, о которой все упоминали, строки "Hai" и "Hello" находятся в постоянной памяти. Это означает, что вы не можете удалить их (но вы делаете это в своем деструкторе) - это вызывает сбои. Ваш код не должен присваиваться name напрямую, но должен использовать функцию набора, такую ​​как:

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 *, что может привести к всевозможным проблемам, таким как та, которую вы видите.

1 голос
/ 22 апреля 2010

Вы выделяете один символ и пытаетесь скопировать несколько символов в эту ячейку памяти. Сначала определите длину строки, затем выделите length + 1 символов (дополнительный символ для размещения символа NULL), используя синтаксис new char[length+1]. Вам необходимо соответственно изменить свой деструктор на delete[] name.

0 голосов
/ 22 апреля 2010

Вот код, который отлично работает!

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

Спасибо всем за точку зрения. Это действительно помогло!

0 голосов
/ 22 апреля 2010

Вам необходимо выделить достаточно памяти для хранения информации, которую вы пытаетесь сохранить. «Hai» - это 4 байта или символа (включая нулевой терминатор), и вы выделили только один. Вы также не копируете строки из одной ячейки памяти в другую, используя «=». Вам нужно распечатать строку поперек.

Используйте std :: string, это сделает вашу жизнь в миллион раз проще:)

0 голосов
/ 22 апреля 2010

Работа 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
...