delete[] не удаляет массивы [дубликат]

Вопрос или проблема

Я создаю класс, который представляет собой 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 и избегать потенциальных ошибок и утечек памяти.

Оцените материал
Добавить комментарий

Капча загружается...