С ++ удаление массива в куче

Мне сложно найти ответ, как конкретно выполнить эту операцию должным образом.

Я хотел бы лучше понять различные способы удаления новой памяти, выделенной в куче, особенно в случае двумерного массива.

Для моего примера: У меня есть массив размером 5 в стеке, состоящий из указателей int (int * d [5]). Я инициализирую каждый из этих указателей int в цикле, чтобы создать и указать на массив int размером 8 в куче (d [i] = new int [8]). По сути, я создал двумерный массив (d [j] [k]).

У меня вопрос: каков синтаксис для удаления только отдельных массивов (int [8]) в куче?

В настоящее время у меня это так, но при отладке кажется, что массивы не освобождаются после его выполнения ...

для (int i = 0; i <5; ++ i) удалить d [i];

Что должно быть: «удалить [] d [i]» или просто «удалить [] d» или какой-то другой вариант? Кроме того, есть ли способ удалить отдельные элементы массивов int [8]? Если бы кто-нибудь мог кратко объяснить синтаксис и их различия, это было бы очень полезно. Спасибо!

Я инициализирую каждый из этих указателей int в цикле, чтобы создать и указать на массив int размера ... - это была первая ошибка. std::vector<std::vector<int>> решает почти все проблемы, с которыми вы обязательно столкнетесь, включая возможность последовательного удаления (хотя и потенциально дорого). RAII - это то, что на ужин.
WhozCraig 21.10.2018 00:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
1 644
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы распределили массивы через d[i] = new int[8], то вы должны удалить их через delete[] d[i]. Невозможно освободить отдельные элементы такого массива, не освободив целиком.

Понятно, спасибо. Я пробовал удалить [] d [i]; но вроде бы не получилось. В отладчике (gdb) он все еще показывает, что массивы int [8] существуют после удаления и содержат все значения, которыми я их инициализировал? Я не знаю, что делать ...

MajinMilad 20.10.2018 23:59

@MajinMilad Тот факт, что отладчик показывает, что память не повреждена, не означает, что вам разрешен программный доступ к ней. Для этого вызовет неопределенное поведение.

WhozCraig 21.10.2018 00:07

@MajinMilad Когда вы освобождаете память, это просто означает, что она помечена как свободная для использования в дальнейшем. Он не перезаписывается сразу.

Joseph Sible-Reinstate Monica 21.10.2018 00:08

Оооо, хорошо, это имеет большой смысл. Значит, он помечен как свободный для дальнейшего распределения, но все еще может содержать свои старые значения до перераспределения и перезаписи?

MajinMilad 21.10.2018 03:01

Точно. В этом отношении это похоже на удаленные файлы на жестком диске.

Joseph Sible-Reinstate Monica 21.10.2018 03:02

Кроме того, значит, он работает? Что правильно "удалить [] d [i]" или "удалить d [i]"

MajinMilad 21.10.2018 03:02

Первое, как и сказано в моем ответе.

Joseph Sible-Reinstate Monica 21.10.2018 03:02

@MajinMilad, если ваша проблема решена, поставьте галочку, чтобы отметить ответ как принятый.

Joseph Sible-Reinstate Monica 21.10.2018 03:13

вы упомянули, что распределяете внутренние массивы внутри цикла. который, как мне кажется, выглядит примерно так.

int*d[2];
for (int i = 0; i < 2; i++)
{
    d[i] = new int[3];
}

Обратите внимание, что d[2] содержит только указатели на массивы. поэтому, чтобы удалить этот массив, вам нужно перебрать каждый набор указателей массива и вызовите delete [] d [i];

for (int i = 0; i < 2; i++)
{
        delete[] d[i];
}

В качестве дополнительного примечания было бы очень полезно знать, как ваша IDE пытается обнаружить повреждения памяти.

например в визуальной студии (в режиме DEBUG)

  • 0xCD означает, что память выделена через malloc или new, но никогда не записывается приложение.
  • 0xCC означает неинициализированные переменные.
  • 0XDD означает, что память была освобождена с помощью удаления или освобождения.
  • 0xFD означает ограждение памяти и действует как охранник. используется для обнаружения массивов индексации, выходящих за границы.

Имея это в виду, давайте посмотрим, сможем ли мы понять, что делает среда IDE при выполнении приведенного выше кода.

Когда d-массив объявлен как int*d[2];, структура памяти выглядит следующим образом; обратите внимание, что массив d имеет два элемента, но ни один из них не имеет начальных значений, поэтому они назначаются 0xCC

давайте посмотрим, что произойдет после того, как мы сделаем d[i] = new int[3]; обратите внимание, что теперь массив d состоит из двух элементов, каждый из которых содержит массив типа int. значения, которые вы видите, являются адресами указателей на массив, для которого мы выделили память.

поскольку мы знаем адреса, мы можем заглянуть в память и увидеть, что там происходит при выделении и удалении каждого массива.

например, после того, как мы выделим наш второй массив int в цикле for, расположение памяти будет выглядеть примерно так;
обратите внимание, что весь элемент массива имеет 0xCD с окончанием на 0xFD. Это будет указывать в моей среде IDE, что память выделена и окружена ограждением.

Давайте посмотрим, что произойдет, когда d[2] будет удален.

Понятно, спасибо. "delete [] d [i]" освободит память в куче (int [3]), на которую указывает d [i], правильно? Он не удаляет фактический указатель d [i]

MajinMilad 23.10.2018 00:30

@MajinMilad, это правильно. думайте об этом так. указатель - это переменная, которая просто содержит значение адреса объекта, на который он должен указывать. конечно, это может быть нулевой ptr, если он ни на что не указывает, или недействительный указатель, если он указывает на уже удаленный объект.

Yucel_K 23.10.2018 00:46

@MajinMilad, вы можете найти больше ответа здесь stackoverflow.com/questions/23621677/…

Yucel_K 23.10.2018 00:47

извините, но у меня есть класс MC с двумя членами, объект enum и char. У меня есть указатель на этот класс в виде карты, и я использую MC* map = new MC[1050]. Я отношусь к нему как к 2d-массиву, и он работает нормально, пока игрок не умрет, игра не закончится и не пришло время для карты быть deleteed, delete[] map выкидывает Invalid address specified to RtlValidateHeap([some address], [some address]), и программа вылетает, какие-нибудь предложения?

platinoob_ 08.09.2020 13:29

Другие вопросы по теме