首页 > 解决方案 > “检测到 CRT ......堆损坏”错误与析构函数

问题描述

我正在尝试在我的班级上使用析构函数,但它给了我一个错误:

CRT 检测到应用程序在结束或堆缓冲区后写入内存

以下是完整代码:

#include <iostream>
#include <string.h>
using namespace std;

class Autor {
    char* name;char* surname;
public:
    Autor(char* nam, char* surnam) {
        name = new char[strlen(nam)];
        surname = new char[strlen(surnam)];
        strcpy(name, nam);
        strcpy(surname, surnam);
    };

    Autor() {
        name = new char;
        surname = new char;
        *name = '-';
        *surname = '-';
    };

    Autor(Autor& a)
    {
        name = new char[strlen(a.name)+1];
        surname = new char[strlen(a.surname)+1];
        strcpy(name, a.name);
        strcpy(surname, a.surname);      
    };
   
    char* getName() { return name; };
    char* getSurname() { return surname; };

    Autor& setName(char* nam) {
        name = new char[strlen(nam)];
        strcpy(name, nam);
        return *this;
    };

    Autor& setSurname(char* surnam) {
        surname = new char[strlen(surnam)];
        strcpy(surname, surnam);
        return *this;
    };

    void print1() {
        cout << "First print type: " << name << " "<< surname<<"\n";
    };

    void print2()
    {
        cout << "Second print type: " << "Author, name: " << name <<"\n";
    };

    ~Autor() {
        if (name)
        {
            delete[] name;
        }
        if (surname)
        {
            delete[] surname;
        }
    };
};

class Book {
    char* name;
    char* codeUDK;
    Autor auth;
    int year;
    int numPages;
public:
    Book(char* nam, char* code, Autor a, int yea, int numP)
    {
        name = new char[strlen(nam)];
        codeUDK = new char[strlen(code)];
        strcpy(name, nam);
        strcpy(codeUDK, code);
        auth = a;
        year = yea;
        numPages = numP;
    };

    Book()
    {
        name = new char;
        strcpy(name, "x");
        codeUDK = new char[2];
        strcpy(codeUDK, "x");
        char* nameAuth;
        nameAuth = new char;
        char* surnameAuth;  
        strcpy(nameAuth,"x");
        surnameAuth = new char[2];
        strcpy(surnameAuth, "x");
        auth.setName(nameAuth);
        auth.setSurname(surnameAuth);
        year = 0;
        numPages = 0;
    };

    char* getName() { return name; };
    char* getCode() { return codeUDK; };
    Autor getAuth() { return auth; };
    int getYear(){ return year;};
    int getNumPages() { return numPages; };

    Book& setName(char* nam)
    {
        name = new char[strlen(nam)];
        strcpy(name, nam);
        return *this;
    };

    Book& setCode(char* code)
    {
        codeUDK = new char[strlen(code)];
        strcpy(codeUDK, code);
        return *this;
    };

    Book& setAuth(Autor a)
    {
        auth = a;
        return *this;
    };

    Book& setYear(int yea)
    {
        year = yea;
        return *this;
    };

    Book& setNumPages(int num)
    {
        numPages = num;
        return *this;
    };

    Book(Book& a)
    {
        name = new char[strlen(a.name)+1];
        strcpy(name, a.name);
        codeUDK = new char[strlen(a.codeUDK)+1];
        strcpy(codeUDK, a.codeUDK);
        auth = a.auth;
        year = a.year;
        numPages = a.numPages;
    }

    ~Book()
    {
        if (name)
        {
            delete[] this->name;
        }
        if (codeUDK)
        {
            delete[] this->codeUDK;
        }
    }

    void print1() {
        cout <<"First print type: "<< name << " code: " << codeUDK << " author's name: " << auth.getName() << " author's surname: " << auth.getSurname() << " year of writing " << year << " amount of pages: " << numPages<<"\n";
    };

    void print2() {
        cout << "Second print type: " << "Book, name and author: " << name << ", Author: " << auth.getName() << auth.getSurname();
    };
};

int main()
{
    char nameA[20] = "George", surnameA[20] = "Orwell";
    Autor auth;  
    cout << "enter name and surname: ";
    auth.setName(nameA).setSurname(surnameA);
    Autor auth1(auth);
    auth.print1();
    auth.print2();
    cout << "\ncopied author:\n";
    auth1.print1();
    auth1.print2();
    Book myBook;
    char nameB[15] = "1984",codeUDKB[15]="23481-b";
    int nump = 234,yearB=1896;
    myBook.setName(nameB).setAuth(auth).setCode(codeUDKB).setNumPages(nump).setYear(yearB);
    myBook.print1();
    myBook.print2();
    return 0;
}

标签: c++

解决方案


这段代码有很多错误:

  • Autor并且Book不完全遵循3/5/0 的规则,因为它们都缺少operator=赋值运算符,因此对象之间的赋值将浅拷贝字符串成员而不是深拷贝它们,从而导致运行时的双重删除错误。特别是在这种情况下Autor,这尤其会导致 5 参数的Book()构造函数和Book::setAuth()方法出现问题。

  • 2 参数Autor()构造函数和 5 参数Book()构造函数没有在其字符串成员中为空终止符分配空间,因此调用strcpy()将破坏内存。和复制构造函数可以正确处理这个问题Autor()Book()

  • 默认值Autor()和构造函数使用而不是Book()分配它们的字符串成员,这将与它们的析构函数不匹配。此外,它们也没有在其字符串成员中为空终止符分配空间。newnew[]delete[]

  • 默认Book()构造函数正在泄漏内存,因为它没有delete[]在本地分配nameAuth和字符串。surnameAuth根本不需要动态分配这些字符串。

  • , Autor::setName(),Autor::setSurname()和方法都在泄漏内存Book::setName()Book::setCode()因为它们没有释放被替换的旧字符串。此外,它们不会为新字符串中的空终止符分配空间。

  • main()正在提示用户输入,但实际上并未读取用户的输入。

综上所述,尝试更多类似的东西:

#include <iostream>
#include <string.h>
using namespace std;

class Autor {
    char* name;
    char* surname;

public:
    Autor() {
        name = new char[2];
        strcpy(name, "-");
        surname = new char[2];
        strcpy(surname, "-");
    }

    Autor(const char* nam, const char* surnam) {
        if (!nam) nam = "-";
        if (!surnam) surnam = "-";
        name = new char[strlen(nam)+1];
        strcpy(name, nam);
        surname = new char[strlen(surnam)+1];
        strcpy(surname, surnam);
    }

    Autor(const Autor& a)
    {
        name = new char[strlen(a.name)+1];
        strcpy(name, a.name);
        surname = new char[strlen(a.surname)+1];
        strcpy(surname, a.surname);      
    }
   
    ~Autor() {
        delete[] name;
        delete[] surname;
    }

    Autor& operator=(const Autor& a) {
        if (this != &a) {
            setName(a.getName());
            setSurname(a.getSurname());
        }
        return *this;
    }

    const char* getName() const { return name; };
    const char* getSurname() const { return surname; };

    Autor& setName(const char* nam) {
        if (!nam) nam = "-";
        char *new_name = new char[strlen(nam)+1];
        strcpy(new_name, nam);
        delete[] name;
        name = new_name;
        return *this;
    }

    Autor& setSurname(const char* surnam) {
        if (!surnam) surnam = "-";
        char *new_surname = new char[strlen(surnam)+1];
        strcpy(new_surname, surnam);
        delete[] surname;
        surname = new_surname;
        return *this;
    }

    void print1() const {
        cout << "First print type: " << name << " " << surname << "\n";
    }

    void print2() const
    {
        cout << "Second print type: " << "Author, name: " << name << "\n";
    }
};

class Book {
    char* name;
    char* codeUDK;
    Autor auth;
    int year;
    int numPages;

public:
    Book()
        : auth("x", "x")
    {
        name = new char[2];
        strcpy(name, "x");
        codeUDK = new char[2];
        strcpy(codeUDK, "x");
        year = 0;
        numPages = 0;
    }

    Book(const char* nam, const char* code, const Autor &a, int yea, int numP)
        : auth(a)
    {
        if (!nam) nam = "x";
        if (!code) code = "x";
        name = new char[strlen(nam)+1];
        strcpy(name, nam);
        codeUDK = new char[strlen(code)+1];
        strcpy(codeUDK, code);
        year = yea;
        numPages = numP;
    }

    Book(const Book& a)
        : auth(a.auth)
    {
        name = new char[strlen(a.name)+1];
        strcpy(name, a.name);
        codeUDK = new char[strlen(a.codeUDK)+1];
        strcpy(codeUDK, a.codeUDK);
        year = a.year;
        numPages = a.numPages;
    }

    ~Book()
    {
        delete[] name;
        delete[] codeUDK;
    }

    Book& operator=(const Book& b) {
        if (this != &b) {
            setName(b.getName());
            setCode(b.getCode());
            setAutor(b.getAuth());
            setYear(b.getYear());
            setNumPages(b.getNumPages());
        }
        return *this;
    }

    const char* getName() const { return name; }
    const char* getCode() const { return codeUDK; }
    Autor& getAuth() { return auth; }
    const Autor& getAuth() const { return auth; }
    int getYear() const { return year; }
    int getNumPages() const { return numPages; }

    Book& setName(const char* nam)
    {
        if (!nam) nam = "x";
        char *new_name = new char[strlen(nam)+1];
        strcpy(new_name, nam);
        delete[] name;
        name = new_name;
        return *this;
    }

    Book& setCode(const char* code)
    {
        if (!code) code = "x";
        char *new_code = new char[strlen(code)+1];
        strcpy(new_code, code);
        delete[] codeUDK;
        codeUDK = new_code;
        return *this;
    }

    Book& setAuth(const Autor &a)
    {
        auth = a;
        return *this;
    }

    Book& setYear(int yea)
    {
        year = yea;
        return *this;
    }

    Book& setNumPages(int num)
    {
        numPages = num;
        return *this;
    }

    void print1() const {
        cout << "First print type: " << name << " code: " << codeUDK << " author's name: " << auth.getName() << " author's surname: " << auth.getSurname() << " year of writing " << year << " amount of pages: " << numPages << "\n";
    }

    void print2() const {
        cout << "Second print type: " << "Book, name and author: " << name << ", Author: " << auth.getName() << auth.getSurname() << "\n";
    }
};

int main()
{
    char nameA[20], surnameA[20];

    cout << "enter name and surname: ";
    cin.get(nameA, 20);
    cin.get(surnameA, 20);

    Autor auth(nameA, surnameA);
    Autor auth1(auth);
    auth.print1();
    auth.print2();
    cout << "\ncopied author:\n";
    auth1.print1();
    auth1.print2();

    Book myBook("1984", "23481-b", auth, 1896, 234);
    myBook.print1();
    myBook.print2();

    return 0;
}

话虽这么说,你真的应该使用std::string而不是char[],让编译器为你处理所有的内存管理,例如:

#include <iostream>
#include <string>
using namespace std;

class Autor {
    string name;
    string surname;

public:
    Autor()
        : name("-"), surname("-")
    {
    }

    Autor(const string& nam, const string& surnam)
        : name(nam), surname(surnam)
    {
        if (name.empty()) name = "-";
        if (surname.empty()) surname = "-";
    }

    string getName() const { return name; };
    string getSurname() const { return surname; };

    Autor& setName(const string& nam) {
        name = nam;
        if (name.empty()) name = "-";
        return *this;
    }

    Autor& setSurname(const char* surnam) {
        surname = surnam;
        if (surname.empty()) surname = "-";
        return *this;
    }

    void print1() const {
        cout << "First print type: " << name << " " << surname << "\n";
    }

    void print2() const
    {
        cout << "Second print type: " << "Author, name: " << name << "\n";
    }
};

class Book {
    string name;
    string codeUDK;
    Autor auth;
    int year;
    int numPages;

public:
    Book()
        : name("x"), codeUDK("x"), auth("x", "x"), year(0), numPages(0)
    {
    }

    Book(const string& nam, const string& code, const Autor &a, int yea, int numP)
        : name(nam), codeUDK(code), auth(a), year(yea), numPages(numP)
    {
        if (name.empty()) name = "x";
        if (codeUDK.empty()) codeUDK = "x";
    }

    string getName() const { return name; }
    string getCode() const { return codeUDK; }
    Autor& getAuth() { return auth; }
    const Autor& getAuth() const { return auth; }
    int getYear() const { return year; }
    int getNumPages() const { return numPages; }

    Book& setName(const string& nam)
    {
        name = nam;
        if (name.empty()) name = "x";
        return *this;
    }

    Book& setCode(const string& code)
    {
        codeUDK = code;
        if (codeUDK.empty()) codeUDK = "x";
        return *this;
    }

    Book& setAuth(const Autor &a)
    {
        auth = a;
        return *this;
    }

    Book& setYear(int yea)
    {
        year = yea;
        return *this;
    }

    Book& setNumPages(int num)
    {
        numPages = num;
        return *this;
    }

    void print1() const {
        cout << "First print type: " << name << " code: " << codeUDK << " author's name: " << auth.getName() << " author's surname: " << auth.getSurname() << " year of writing " << year << " amount of pages: " << numPages << "\n";
    }

    void print2() const {
        cout << "Second print type: " << "Book, name and author: " << name << ", Author: " << auth.getName() << auth.getSurname() << "\n";
    }
};

int main()
{
    string nameA, surnameA;

    cout << "enter name and surname: ";
    cin >> nameA >> surnameA;

    Autor auth(nameA, surnameA);
    Autor auth1(auth);
    auth.print1();
    auth.print2();
    cout << "\ncopied author:\n";
    auth1.print1();
    auth1.print2();

    Book myBook("1984", "23481-b", auth, 1896, 234);
    myBook.print1();
    myBook.print2();

    return 0;
}

推荐阅读