Запрос освобождения памяти - PullRequest
0 голосов
/ 03 марта 2010

Дополнительная благодарность распространяется на Даниэль Ньюби за ответ на мой вопрос об использовании памяти (и Мартин Йорк за объяснение немного больше) . Это определенно тот ответ, который я искал, но другие мои вопросы ответили другие.

Спасибо всем

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

Я столкнулся с чем-то, в чем я не совсем уверен.

В моей программе я не использую malloc() или free(). Я делаю экземпляры своих классов с new и Я убедился, что каждый из них запускает его destructor, когда он delete 'd , однако, нет вызовов free() или даже установка их указателей (на вещи внутри глобальной области видимости или других классов) на NULL или 0.

То, что я имею в виду под «я в этом уверен», это не то, что я называю каждого деструктора. Я использую только delete для вызова деструктора для запуска, но у меня есть переменные, которые увеличиваются на 1 каждый раз, когда создается объект, и каждый раз, когда запускается его деструктор. Вот как я убедился, что количество созданных мной объектов равно количеству вызываемых деструкторов.

Должен ли я в любом случае использовать malloc() и free()? Должен ли я NULL указывать на то, что я все еще хочу существовать?

Второй вопрос: почему, когда я смотрю на диспетчер задач, мой процесс никогда не «сбрасывает» память? Раньше никогда не переставал набирать, а потом я начал все правильно deleting. Или так я думал.

Не приведет ли free() или delete к снижению использования памяти?

Какую практику следует использовать для mallocfree' памяти со связанными списками?

Ответы [ 6 ]

2 голосов
/ 03 марта 2010

Редко есть причина использовать malloc() и free() в программе на C ++. Палка с new и delete. Обратите внимание, что в отличие от языков с сборкой мусора, установка указателя на NULL или 0 в C ++ не имеет ничего общего с освобождением памяти.

2 голосов
/ 03 марта 2010

вы должны использовать delete с new и free с malloc. delete вызовет деструктор класса, так что вам не нужно явно вызывать его. Цель деструктора - освободить и ресурсы, которые может иметь класс, и delete также освободит память.

Единственный раз, когда вы явно используете деструктор, это когда вы инициализировали свой объект с помощью , поместив новое . Вы должны поставить себя в такое положение, когда сгенерированный компилятором код высвобождает ваши ресурсы - прочитайте эту статью на языке C ++: получение ресурсов - это инициализация .

Также установка нулевого указателя на класс ничего не дает, в фоновом режиме нет сборщика мусора, очищающего вашу память. Если вы не освободите динамическую память в C ++, это будет «утечка» памяти - то есть, нет ссылок на память, и она никогда не будет возвращена до завершения процесса.

p.s., Еще раз не смешивайте пары функций выделения памяти.

edt: не реализуйте связанные списки, используйте контейнеры, предоставляемые стандартной библиотекой шаблонов. Если вы считаете, что вам нужна более высокая производительность, используйте навязчивые контейнеры от boost.

0 голосов
/ 03 марта 2010

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

Это страшно. Вам не нужно заставлять что-либо запускать свой деструктор. Он размещен (новый), уничтожен (удален), конструктор автоматически запускается при новом, а деструктор запускается автоматически при удалении.

однако, нет вызовов free () и даже не устанавливаются их указатели (на вещи внутри глобальной области видимости или другие классы) в NULL или 0.

Нет необходимости использовать malloc / free в коде C ++ (есть несколько ситуаций, когда вы используете библиотеки lib, которые требуют неправильно загруженной памяти, но они явно задокументированы и немногочисленны).

Технически нет необходимости устанавливать указатель на NULL после его удаления.
Это хорошая техника для переменной выходить из области видимости сразу после ее удаления, чтобы ее нельзя было случайно использовать повторно. Если по какой-то причине переменная-указатель живет (то есть не выходит из области видимости) в течение длительного времени после вызова delete, полезно установить ее в NULL, чтобы она не была случайно использована повторно.

Должен ли я в любом случае использовать malloc () и free ()? Должен ли я указывать NULL на то, что я все еще хочу существовать?

Нет и нет.
Примечание: C ++ в отличие от Java не отслеживает, сколько указателей указывают на объект.
Если у вас есть несколько указателей, указывающих на объект, вам нужно использовать умные указатели (вы все равно должны использовать умные указатели).

Второй вопрос: почему, когда я смотрю на диспетчер задач, мой процесс никогда не «сбрасывает» память? Раньше никогда не прекращал набирать, а потом я начал все удалять правильно. Или так я думал.

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

Не приведет ли к освобождению () или удалению использование памяти?

номер

Какую практику следует использовать для освобождения памяти и освобождения памяти с помощью связанных списков?

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

Но если вы используете указатели. вызовите delete, чтобы удалить элемент, затем установите для него значение NULL (область указателя жива еще долго после вызова удаления).

Примечание: boost: shared_pointer очень похож на указатель Java. Он отслеживает количество указателей и удаляет объект при уничтожении последней ссылки на объект. Вам не нужно ничего удалять (точно так же, как в Java), и все, что вам на самом деле нужно, это вызывать новое (как в Java).

0 голосов
/ 03 марта 2010

«Должен ли я в любом случае использовать malloc () и free ()?»

Нет, в большинстве случаев. Придерживайтесь только одной формы управления памятью. Попытка использовать оба средства означает, что вы неизбежно испортите и удалите элемент malloc () или освободите () новый элемент, что приведет к незначительной ошибке. Придерживайтесь одной формы, и вы исправляете эти ошибки заранее.

«Не освободит ли () или удалит использование памяти?»

Операционная система выделяет память в страницах , часто размером 4 КБ. Пока один байт страницы все еще используется, он не будет возвращен в ОС. Вы, вероятно, выделяете много мелких предметов, но не освобождаете их все. (Существуют способы помочь с пользовательским новым / удалить, но они, как правило, не стоят усилий.)

0 голосов
/ 03 марта 2010
  1. new и delete можно более или менее считать версиями malloc для C ++ и бесплатными. Поэтому придерживайтесь одной или другой пары, т. Е. Если указатель был создан с новым, он должен быть освобожден с удалением, что гарантирует упомянутый вами вызов деструктора. Пара malloc / free не поддерживает C ++ и просто выделяет и освобождает блок памяти без присоединенной семантики конструктора / деструктора.

  2. Да, действительно, я считаю хорошей идеей установить указатели на NULL или ноль, когда они были освобождены или удалены. Во время отладки я также иногда устанавливал для них что-то характерное, например 0xdeadbeef, чтобы они выделялись.

  3. Вполне вероятно, что "использование памяти" ОС отражает весь размер кучи вашего процесса, а не представление вашего менеджера памяти о том, сколько памяти выделено. Когда распределитель обнаруживает, что ему не хватает места в куче, он увеличивает кучу, и это будет отражаться в «использовании памяти», которое вы просматриваете. Теоретически можно было бы соответственно уменьшить объем памяти при освобождении памяти, но это не всегда происходит. Таким образом, вы можете видеть только увеличение использования памяти и никогда не сокращение.

0 голосов
/ 03 марта 2010

Вы должны использовать new и delete в предпочтении для malloc () / calloc () / realloc () и free ().

Если вы создаете связанные списки, вы должны использовать std :: list. Также посмотрите на std :: vector

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...