内存泄漏和崩溃与删除[]

Memory leak and crash with delete[]

本文关键字:删除 崩溃 泄漏 内存      更新时间:2023-10-16

我有一个内存泄漏的程序,每次我向代码添加删除时,它都会崩溃。我只是想知道是否有人知道为什么会发生这种情况。崩溃的代码如下。这是删除的破坏者名字和姓氏声明如下。

char* firstName;
char* lastName;

Name::~Name(){
    delete[] firstName;
    delete[] lastName;
}

这是分配内存的地方

Name::Name(Name& name){
    //copys the first and last name from one Name to the other
    firstName = new char [strlen(name.firstName)+1];
    strcpy(firstName,name.firstName);
    lastName = new char [strlen(name.lastName)+1];
    strcpy(lastName,name.lastName);
}
很可能

您在某个时候分配了Name类型的对象并且没有复制赋值(首先我以为没有复制构造函数,但您实际上显示了您的复制构造函数)。默认生成的复制分配仅执行按位复制。因此,您会在某个时候看到指针的双delete[](也存在内存泄漏,但这并不明显)。或者,您的其他构造函数是什么样的?是否有可能不初始化指针的默认构造函数或可能最终存储指向字符串文字的指针的构造函数?

最好的方法不是使用手动内存分配,而是使用 std::string .如果你不能使用std::string,例如,因为这是一个赋值,我强烈建议你实现你自己的简单字符串类:处理多个分配的实体而不将每个实体单独包装到合适的资源维护类中是非常困难的。我做不好。诚然,我只在大约 20 年的时间里C++编程。

例如,复制构造函数不是异常安全的:如果第二个分配由于没有足够的内存来分配而引发异常,则存在资源泄漏。有一些方法可以处理函数级的try/catch块,但使用字符串类要容易得多:如果构造函数抛出异常,任何完全构造的子对象都会被自动销毁。这样,字符串的构造函数就会处理内存。

假设firstNamelastNameName类的正确元素,你应该注意strlen不会检查NULL,所以你应该处理NULL

Name::Name(const Name& name){
    if (name.firstName) {
        int len_z = strlen(name.firstName)+1;
        firstName = new char [len_z];
        strncpy(firstName, name.firstName, len_z);
        // ^^^ also copy the terminator char ^^^
    } else {
        firstName = NULL;
    }
    // repeat for lastName:
    if (name.lastName) {
        int len_z = strlen(name.lastName)+1;
        lastName = new char [len_z];
        strncpy(lastName, name.lastName, len_z);
    } else {
        lastName = NULL;
    }
}

或者使用如下所示的构造函数创建标准Name对象:

Name::Name() {
    firstName = new char[1];
    firstName[0] = '';
    // repeat for lastName:
    lastName = new char[1];
    lastName[0] = '';
}

至少在这里你明白了,为什么std::string是一个更好的选择:它是一个实现你需要的字符串所有方面的类。如果你手工制作,你必须把名字和姓氏加倍......想象一下,您的Name类的下一个版本中很快就会有middleName......