Вопрос или проблема
Я создаю класс, который представляет собой Matrix
. Для этого я создал массив указателей на double
. Поэтому я пытаюсь реализовать деструктор для этого класса Matrix
, но delete[]
не работает так, как ожидалось. Вот код:
Matrix::Matrix(int r, int c):rowsM(r), colsM(c)
{
matrixM = new double* [rowsM];
assert(matrixM != NULL);
for(int i=0; i < rowsM; i++){
matrixM[i] = new double[colsM];
assert(matrixM[i] != NULL);
}
sum_rowsM = new double[rowsM];
assert(sum_rowsM != NULL);
sum_colsM = new double[colsM];
assert(sum_colsM != NULL);
}
void Matrix::destroy()
{
for(int i=0; i < rowsM; i++){
delete[] matrixM[i];
assert(matrixM[i] == NULL);
}
delete[] matrixM;
assert(matrixM != NULL);
delete[] sum_rowsM;
assert(sum_rowsM == NULL);
delete[] sum_colsM;
assert(sum_colsM == NULL);
}
Я пробовал использовать delete
без успеха, поэтому я изучил это и выяснил, что delete[]
был лучшим выбором, но результат на Cygwin (который я использую для компиляции) таков:
assertion "matrixM[i] == NULL" failed: file "matrix.cpp", function: void Matrix::destroy()
Aborted
это означает, что delete явно не сработал. Пожалуйста, помогите.
Ваше понимание new/new[]
и delete/delete[]
неверно, и все вызовы assert
в вашем коде должны быть удалены.
Во-первых, new
и new[]
никогда не возвращают NULL
в случае ошибки. Если они не удались, они выдают исключение std::bad_alloc
.
Во-вторых, delete
и delete[]
не изменяют свои аргументы. В частности, они не устанавливают аргумент в NULL
.
Кроме проблем с assert
, ваш код правильный (насколько можно судить по представленному коду).
Ответ или решение
Проверка и исправление проблем с удалением массивов в классе Matrix
При разработке класса Matrix
и реализации деструктора могут возникнуть проблемы, связанные с использованием операторов delete[]
, которые не удаляют массивы должным образом. Давайте детально рассмотрим ваш код и выявим основные проблемы, которые могут приводить к ошибкам.
1. Понимание работы new и delete
Сначала важно помнить, что оператор new
всегда должен использоваться в сочетании с delete
, а new[]
с delete[]
. Если выделение памяти через new
или new[]
не удается, оно выбрасывает исключение std::bad_alloc
, а не возвращает NULL
. Таким образом, проверки на NULL
после вызовов new
не являются корректными.
2. Ситуация с assert
Ваш код использует оператор assert
для проверки значений указателей после их удаления:
assert(matrixM[i] == NULL);
Это ошибка, поскольку delete[]
не устанавливает указатели в NULL
. Указатель по-прежнему указывает на область памяти (хоть и освобожденную), и ваше утверждение будет проваливаться. Вместо этого, после использования delete[]
, рекомендуется установить указатель в NULL
вручную, чтобы избежать последующих ошибок.
3. Исправленный метод destroy
Вот исправленный метод destroy
, который учитывает вышеизложенные замечания:
void Matrix::destroy()
{
for(int i = 0; i < rowsM; i++){
delete[] matrixM[i]; // Освобождаем память каждой строки
matrixM[i] = NULL; // Устанавливаем в NULL, чтобы избежать "висячих" указателей
}
delete[] matrixM; // Освобождаем память для массива указателей
matrixM = NULL; // Устанавливаем указатель в NULL
delete[] sum_rowsM; // Освобождаем память для массива сумм строк
sum_rowsM = NULL; // Устанавливаем указатель в NULL
delete[] sum_colsM; // Освобождаем память для массива сумм столбцов
sum_colsM = NULL; // Устанавливаем указатель в NULL
}
4. Резюме
- Убедитесь, что после каждого вызова
delete[]
устанавливаете указатели вNULL
. - Убирайте проверки на
NULL
после использованияnew
, поскольку это не корректный подход в C++. - Будьте внимательны с использованием
assert
, так как они должны проверять лишь условия, которые вы действительно ожидаете, а не состояние указателей после их освобождения.
Следуя этим рекомендациям, вы сможете эффективно управлять памятью в вашем классе Matrix
и избегать потенциальных ошибок и утечек памяти.