Почему код не работает в деструкторе? - PullRequest
0 голосов
/ 21 октября 2018

Я прошел через вопросы о стековом потоке, похожие на «Почему деструктор вызывается дважды?».Мой вопрос может быть похожим, но с небольшим изменением.Я получаю сообщение об ошибке при выполнении следующего кода:

struct Employee{
        char *name;
        char *tag;
        Employee *employee;

        Employee(){
            name = NULL;
            tag = NULL;
            employee = NULL;
        }
        //copy constructor
        Employee(const Employee &obj){
            cout << "Copy constructor called" << endl;
            name = (char*)malloc(sizeof(char)*strlen(obj.name));
            strcpy(name, obj.name);
            tag = (char*)malloc(sizeof(char)*strlen(obj.tag));
            strcpy(tag, obj.tag);
            employee = (struct Employee*)malloc(sizeof(obj.employee));
            employee = obj.employee;
        }
        //overloaded assignment operator
        void operator = (const Employee &obj){
            cout << "Assignment operator called" << endl;
            if (this == &obj){
                return;
            }
            strcpy(name, obj.name);
            strcpy(tag, obj.tag);
            employee = obj.employee;

        }
        //destructor
        ~Employee(){
            cout << "Destructor called" << endl;
            if (name != NULL){
                cout << "Freeing name" << endl;
                free(name);
                name = NULL;
            }
            if (tag != NULL){
                cout << "Freeing tag" << endl;
                free(tag);
                tag = NULL;
            }
            if (employee != NULL){
                cout << "Freeing employee" << endl;
                free(employee);
                employee = NULL;
            }
        }
};
Employee createNode(){
        Employee emp;
        emp.name = (char*)malloc(sizeof(char)* 25);
        strcpy(emp.name, "Alan");
        emp.tag = (char*)malloc(sizeof(char)* 25);
        strcpy(emp.tag, "Engineer");
        emp.employee = (struct Employee*)malloc(sizeof(struct Employee));//just created memory, no initialization
        return emp;
}
Employee get(){
        //Employee emp = createNode();
        //return emp;
        return createNode();
}

int main(){
        Employee emp = get();

        getchar();
        return 0;
}

Я отладил код и обнаружил, что ошибка возникает при повторном вызове деструктора при выходе из основной функции.

1) Я хочу знать, почему код не запускается?

2) Есть ли утечки памяти?

3) Как исправить ошибку, правильно освобождая память?

Заранее спасибо.

Обновление:

В соответствии с тремя Правилами я также добавил конструктор копирования и перегрузил оператор присваивания.Но ошибка (выражение: _crtisvalidheappointer (puserdata)) возникает.После проверки в Google я мог видеть, что кое-где происходит повреждение кучи.Когда я комментировал инициализацию сотрудника-члена Struct в createNode (), я мог видеть повышение ошибки при попытке освободить сотрудника в деструкторе.Поэтому я подозреваю, что проблема в члене структуры работника.Пожалуйста, помогите мне с этим. Я использую Visual Studio для отладки и запуска.

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Только что попробовал ваш код и обнаружил несколько проблем, вызывающих сбой:

1) strlen возвращает длину строки без нулевого символа-терминатора, но strcpy требует дополнительного байта, поэтому ваше распределение должно выглядеть следующим образом:

name = (char*)malloc(strlen(obj.name)+1);

2) При копировании employee , вы копируете указатель, поэтому у вас есть утечка памяти и указатель employee как висячий.

Также malloc не может работать с конструкторами, поэтому после

employee = (struct Employee*)malloc(sizeof(obj.employee));

сотрудник имеет мусор внутри.

0 голосов
/ 21 октября 2018

Ваша проблема в отсутствии класса копирования и оператора присваивания в вашем классе.В результате вы освобождаете строки внутри класса несколько раз.

...