Как правильно освободить память? - PullRequest
0 голосов
/ 11 марта 2020

Классы:

class Menuitem
{
private:
    char* text;

    Menuitem();
    Menuitem(const char*);
    ~Menuitem();
    Menuitem(const Menuitem& ) = delete;
    Menuitem& operator=(const Menuitem& ) = delete;
    friend class Menu;
public:
};

class Menu
{
private:
    char* title;
    Menuitem* items;
    int identation = 0;
    int amount = 0;
public:
    Menu();
    Menu(const char*, int = 0);
    ~Menu();
    bool isEmpty() const;
    int run() const;
    void add(const char*);
    void display() const;
    Menu& operator=(const char* nTitle);
    operator int() const;
    Menu& operator=(const Menu& );
    operator bool() const;
    Menu& operator<<(const char* );
};

Функции:

Menu& Menu::operator=(const char* nTitle)
{
    if (nTitle[0] != '\0' && title[0] != '\0')
    {
        delete[] title;
        title = new char[strlen(nTitle)+1];
        strcpy(title, nTitle);
    }
    else if (title[0] != '\0' && nTitle == 0)
    {
        delete[] title;
        title = nullptr;
    }
    else
    {
        title = nullptr;
    }
    return *this;
}

Menu& Menu::operator=(const Menu& nMenu)
{
    if (nMenu.title[0] != '\0' && title[0] != '\0')
    {
        delete[] title;
        title = new char[strlen(nMenu.title)+1];
        strcpy(title, nMenu.title);
    }
    else if (nMenu.title[0] == '\0' && title[0] != '\0')
    {
        delete[] title;
        title = nullptr;
    }
    else
    {
        title = nullptr;
    }


    if (!amount)
        for (int i = 0; i < amount; i++)
        {
            if (items[i].text[0] != '\0')
            {
                delete[] items[i].text;
                items[i].text = nullptr;
            }
        }
    amount = 0;

    for (int i = 0; i < nMenu.amount; i++)
    {
        if (nMenu.items[i].text != nullptr)
        {
            items[i].text = new char[strlen(nMenu.items[i].text)+1];
            strcpy(items[i].text, nMenu.items[i].text);
        }
        else
        {
            items[i].text = nullptr;
        }
    }
    amount = nMenu.amount;
    identation = nMenu.identation;
    return *this;
}

В моем коде много функций, но я думаю, что эти (или, возможно, одна из этих) функций вызывают ошибку. Код отображает то, что мне нужно, но в конце концов, когда я очищаю указатели из меню, используя деструктор

Menu :: ~ Menu () {delete [] title; delete [] items;}

Я получаю следующие ошибки:

mallo c: неверная контрольная сумма для освобожденного объекта 0x102832838: возможно, изменена после освобождения.

Может быть, я пытаюсь что-то дважды удалить, но не могу найти что и где

1 Ответ

2 голосов
/ 11 марта 2020

Как правильно освободить память?

Управляя выделением с помощью контейнера RAII, например std::string.


Если вам необходимо выполните ручное управление памятью, затем следуйте этим правилам:

  • Никогда не управляйте памятью в каком-либо классе, кроме класса, единственной обязанностью которого является управление этой памятью.
  • Всегда имейте только одно удаление для каждого новый. Никогда не удаляйте ничего более одного раза.
  • Используйте только delete для new и delete[] для new[].
  • Никогда не удаляйте ничего, что не было возвращено новым.
  • Всегда инициализируйте указатель-владелец в каждом конструкторе.
  • Никогда не позволяйте указателю-владельцу указывать на что-либо, кроме действительного объекта или nullptr, в качестве инварианта класса.
  • Никогда не допускайте владение указатель имеет то же значение, что и другой объект, что и инвариант класса.
  • Никогда не назначайте указатель-владелец, если только вы не удалили его.
  • Никогда не удаляйте указатель-владелец, если вы сразу не назначите допустимое значение к нему (кроме деструктора, где вам нужно только удалить).
  • Никогда не удаляйте указатель где-либо, кроме класса, в котором вы его разместили.
  • Реализуйте все пять деструкторов, copy / переместить конструктор / назначение.

Возможно, я пытаюсь что-то удалить дважды, но не могу найти что и где

Начать с Creat mcve .

...