У меня есть класс с именем «Меню», у этого класса есть массив указателей на объекты класса «MenuItem». Первые три соответствующие строки класса Menu выглядят так:

class Menu
{
    MenuItem *items[5];

В конструкторе класса меню я создаю items как:

for(int i=0; i<nItems; i++)
{
    items[i] = new MenuItem(titles[i],...); //with all necessary parameters

В деструкторе класса Menu я удаляю items как:

~Menu()
{
for(int i=0; i<nItems; i++)
    delete items[i];

Проблема: Моя проблема в том, что когда я вызываю этот деструктор, я получаю ошибку Debug Assertion Failed!. За исключением этого деструктора. Все работает отлично. Если я не вызываю этот деструктор, ошибки не возникает. Я хочу знать, как решить эту проблему? Я хочу удалить этот массив, чтобы очистить память.

1
Ali Mohyudin 27 Авг 2014 в 14:27
Если nItems <= 5, то все в порядке, поэтому проблема должна быть где-то еще
 – 
glezmen
27 Авг 2014 в 14:31
Да в моей программе nItems=4
 – 
Ali Mohyudin
27 Авг 2014 в 14:33
1
Но что за утверждение?
 – 
quantdev
27 Авг 2014 в 14:37
Я ничего об этом не знаю!
 – 
Ali Mohyudin
27 Авг 2014 в 14:40
Управление памятью сложно; вы, вероятно, неправильно следовали правилу трех. Почему бы не использовать std::vector и/или std::unique_ptr, которые специально разработаны для правильного управления памятью, а не жонглировать указателями и надеяться на лучшее?
 – 
Mike Seymour
27 Авг 2014 в 14:49

2 ответа

Лучший ответ

Трудно сказать, в чем проблема, без дополнительного контекста (хотя я бы сделал ставку на проблему с конструктором копирования и / или оператором присваивания, или с неправильным значением для nItems).

Лучший способ управлять этими необработанными указателями - вообще не иметь их.

Рассмотреть возможность :

Массив умных указателей:

std::unique_ptr<MenuItem> items[5];

Или std::array умных указателей:

std::array<std::unique_ptr<MenuItem>, 5> items;

Или vector<> умных указателей:

std::vector<std::unique_ptr<MenuItem>> items;
3
quantdev 27 Авг 2014 в 14:43
Как я буду инициализировать эти векторы MenuItem?
 – 
Ali Mohyudin
27 Авг 2014 в 22:30
1
Используйте items.push_back(std::unique_ptr<MenuItem>(new MenuItem(...))); Надеюсь, это поможет.
 – 
quantdev
27 Авг 2014 в 22:31
Ох, ну ладно! Мне придется изменить все в моем коде только из-за этого! Но в любом случае попробую!
 – 
Ali Mohyudin
27 Авг 2014 в 22:36
Не так уж и много, вот увидишь. С другой стороны, вам не нужен ни деструктор (ни оператор присваивания), который избавит вас от большего количества ошибок.
 – 
quantdev
27 Авг 2014 в 22:38
Еще один вопрос: а не надо ли удалять данные из этого вектора?
 – 
Ali Mohyudin
27 Авг 2014 в 22:44

Я не вижу ничего плохого в опубликованном вами коде.

Хотя утверждение происходит, когда объекты уничтожаются, очевидная ошибка возникает в другом месте; в какой-то момент в течение жизни объекта что-то нацарапано.

Утверждение отладки такого рода не означает, что «ошибка произошла сейчас!». По сути, это означает, что «ошибка произошла некоторое время назад, и я ее только что заметил!».

Найдите ошибку в другом месте вашего кода. Существует ряд инструментов отладки, которые могут инструментировать код и пытаться идентифицировать неопределенное поведение, например использование неинициализированной или нераспределенной памяти.

1
Sam Varshavchik 27 Авг 2014 в 15:07
На самом деле моя программа работает абсолютно нормально без удаления массива объектов в деструкторе.
 – 
Ali Mohyudin
27 Авг 2014 в 22:19
1
Какая-то другая часть вашего кода, очевидно, вызывает повреждение памяти. Это то, что говорит вам отладочное утверждение. Если вы явно не освободите память, выделенную для этого объекта, процесс просто завершится. Нет необходимости дополнительно выделять или освобождать память из кучи, поэтому эту проблему не поймать. К сожалению, игнорирование проблемы не заставит ее исчезнуть. Если вам когда-нибудь понадобится добавить код или логику в вашу программу, если вам когда-нибудь понадобится изменить ее каким-либо образом, очень вероятно, что вы все равно нажмете на это утверждение, немедленно завершив его.
 – 
Sam Varshavchik
28 Авг 2014 в 00:39
Я нашел ошибку, мне не нужно было вызывать деструктор для простого объекта (класса Menu) (не указателя на класс Menu).
 – 
Ali Mohyudin
28 Авг 2014 в 06:50