代码之家  ›  专栏  ›  技术社区  ›  hema chandra

为什么代码在析构函数中失败?

  •  0
  • hema chandra  · 技术社区  · 6 年前

    我已经讨论过类似于“为什么调用析构函数两次?”.我的问题可以是类似的,但有一点变化。运行以下代码时出错:

    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))正在引发。在检查了谷歌之后,我可以看到堆腐败发生的地方。当我在createNode()中对结构成员employee的初始化进行注释时,我可以看到试图在析构函数中释放该employee时出现的错误。所以我怀疑问题出在雇员结构成员身上。请帮助我。我正在使用Visual Studio进行调试和运行。

    2 回复  |  直到 6 年前
        1
  •  1
  •   user3344003    6 年前

    您的问题是类中缺少复制构造和分配运算符。因此,您将多次释放类中的字符串。

        2
  •  1
  •   Denis Sablukov    6 年前

    刚刚尝试了您的代码,发现了一些导致崩溃的问题:

    1) 斯特伦 返回不带空终止符字符的字符串长度,但 拷贝字符串 需要额外的字节,因此您的分配应该如下所示:

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

    2)复制时 雇员 ,您复制指针,这样就有内存泄漏和 雇员 指针悬空。

    此外,malloc不能与构造函数一起使用,因此在

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

    雇员 里面有垃圾。