Подтвердить что ты не робот

Указатель NULL - это то же самое, что и его освобождение?

Я работал над фрагментом кода, и на меня нападали сомнения: что происходит с памятью, выделенной для указателя, если я назначаю NULL этому указателю?

Например:

A = new MyClass();

{...do something in the meantime...}

A = NULL;

Пространство по-прежнему выделено, но ссылки на него отсутствуют. Будет ли освобождено это пространство позже, будет ли оно повторно использоваться, останется ли оно в стеке или что?

4b9b3361

Ответ 1

A = new MyClass();

{...do something in the meantime...}

A = NULL;

Как я его отслеживаю, есть два отдельных объекта. Где-то в куче, MyClass экземпляр выделяется new. И в стеке есть указатель с именем A.

A - это просто указатель, нет ничего волшебного, и у него нет специального соединения с выделенным кучей объектом MyClass. Это просто указывает на это прямо сейчас, но это может измениться.

И на последней строке это именно то, что происходит. Вы меняете указатель на то, чтобы указывать на что-то другое. Это не влияет на другие объекты. Он не влияет на объект, на который он ссылался, и не влияет на объект (если он есть), который он настроен для указания на данный момент. Опять же, A - это просто тупой необработанный указатель, как и любой другой. Он может быть NULL, или он может указывать на объект в стеке, или он может указывать на объект в куче, или он может быть неинициализирован и указывать на случайный мусор. Но это все. Он указывает, что он никоим образом не принимает права собственности или не изменяет объект, на который он указывает.

Ответ 2

Это классическая утечка. Как вы говорите, память остается выделенной, но ничто не ссылается на нее, поэтому ее нельзя восстановить, пока процесс не завершится.

Память должна быть удалена с удалением - но с помощью умного указателя (например, std:: auto_ptr или boost:: shared_ptr (или tr1:: shared_ptr), чтобы обернуть указатель, гораздо безопаснее работать с указателями.

Вот как вы можете переписать свой пример с помощью std:: auto_ptr:

std::auto_ptr a( new MyClass() );

/*...do something in the meantime...*/

a.reset();

(Вместо вызова reset() вы можете просто позволить экземпляру auto_ptr выйти из области видимости)

Ответ 3

В большинстве случаев это приведет к утечке памяти в ваш процесс. У вас есть несколько вариантов управления памятью на С++.

  • Используйте delete для освобождения памяти вручную, когда вы закончите с ней. Это может быть трудно получить, особенно в контексте обработки исключений.

  • Используйте интеллектуальный указатель для управления памятью для вас (auto_ptr, shared_ptr, unique_ptr и т.д.)

  • С++ не поставляется с сборщиком мусора, но ничто не мешает вам использовать его (например, Boehm GC), если вы хотите спуститься по этому маршруту.

Ответ 4

Это утечка памяти. Вы должны удалить выделенную память вручную.

Ответ 5

Вам нужно delete A;

Для обычных объектов, устанавливающих указатель на NULL, ничего не делается, кроме как недействительный указатель, объект все еще находится в памяти, это особенно верно, если вы заметили, что у вас может быть более одного указателя на один и тот же объект, t влияет на других.

Ответ 6

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

Ответ 7

В соответствии с комментарием Фила Нэша для каждого нового есть соответствующее удаление, равно как и для каждого malloc, имеется соответствующее свободное. Если соответствующий delete/free не существует, у вас есть утечка.

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

Ответ 8

Нет, он будет потерян для процесса навсегда. У вас будет утечка памяти. Если вы продолжаете это делать, ваша программа в конечном итоге исчерпает память! Чтобы избежать этого, delete объект, когда он вам больше не нужен.

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

Ответ 9

У С++ нет сборщика мусора, как и на некоторых других языках (Java, С#,...), поэтому вы должны сами удалить распределенные объекты.

Ответ 10

Переменные, хранящиеся в стеке, являются локальными переменными каждой функции, например. int large [10]; Переменные, хранящиеся в куче, являются переменными, которые вы инициировали с использованием явных программ распределения памяти, таких как malloc(), calloc(), new() и т.д.

Переменные, хранящиеся в стеке, имеют время жизни, равное времени жизни текущего кадра стека. На английском языке, когда функция возвращается, вы уже не можете считать, что переменные сохраняют то, что вы ожидаете от них. Вот почему его классическая ошибка - вернуть переменную, объявленную локально в функции.

Ответ 11

Назначая NULL указателю, вы не освободите выделенную память. Вы должны вызвать функцию освобождения для освобождения выделенной памяти. В соответствии с С++ Стандарт 5.3.4/8: "Если выделенный тип является типом не-массива, имя функции распределения operator new, а имя функции удаления - operator delete". Я могу предложить следующую функцию для безопасного удаления указателей (с назначением им NULL):

template<typename T>
inline void SafeDelete( T*& p )
{
    // Check whether type is complete.
    // Deleting incomplete type will lead to undefined behavior
    // according to C++ Standard 5.3.5/5.
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);

    delete p;
    p = NULL;
}