2011-12-16 3 views
6

Рассмотрим следующую программу:Когда объект на куче выходят из области видимости

int main() { 

    while(...) { 
     int* foobar = new int; 
    } 

    return 0; 
} 

Когда foobar идут из сферы?

Я знаю, что при использовании new атрибуты выделяются в куче, и их необходимо удалить вручную с помощью delete, в приведенном выше коде, это вызывает утечку памяти. Однако, как насчет сферы?

Я думал, что это исчезнет из области действия, как только цикл while завершится, потому что у вас нет прямого доступа к нему больше. Например, вы не можете delete после завершения цикла.

+0

Это сложно, потому что 'foobar' это указатель, который правильно выходит за рамки и уничтожается (но объект, на который он указывает, не освобождается). «Int» является объектом в куче, не имеет области видимости, и поскольку у вас нет вызова «delete», он просочился. –

ответ

13

Будьте осторожны, foobar является локальным для цикла while, но распределение на куче не имеет области действия и будет уничтожено только в том случае, если вы вызываете delete на нем.

Переменная и распределение не связаны каким-либо образом с компилятором. Действительно, распределение происходит в времени выполнения, поэтому компилятор его даже не видит.

+3

Я рекомендую 'std :: unique_ptr ' –

+7

@MooingDuck: Я рекомендую 'int' ;-p –

+7

@SteveJessop:« int »в день удерживает указатель далеко ... –

2

Указатель (foobar) выйдет за пределы области действия, так как программа попадает в замкнутую скобку цикла while. Поэтому, если выражение в ... остается в силе, память будет просачиваться каждый раз, когда цикл будет выполняться, когда вы потеряли дескриптор выделенного объекта с этой закрывающей скобки.

+1

вы используете 'it' и' this variable', без каких-либо уточнений. Указатель выходит за пределы области действия, объект-объект/объект будет просочиться, поскольку он не имеет области видимости. –

+0

В: «Когда foobar выходит из сферы действия?», A: «Это выйдет из сферы действия ...» Я четко говорю о foobar. Единственная переменная, о которой идет речь, - foobar, pointee/object не является переменной. Обновлено независимо ... –

+0

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

0

Поскольку foobar объявлен в теле цикла, он выходит из области видимости в конце каждой итерации цикла. Затем он обновляется, и новая память выделяется снова и снова, пока цикл не закончится. Фактический объект, который указывает foobar, никогда не выходит за рамки. Область применения не относится к объектам с динамическим распределением (aka heap), только к автоматическим (стек) объектам.

0

foobar выходит за пределы сферы применения после каждого включения петли.

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

9

foobar - локальная переменная, выходящая за пределы области действия в конце блока.

*foobar - динамически распределенный объект с ручным временем жизни. Поскольку у него нет охваченного срока службы, вопрос не имеет смысла - он не имеет область, из которой он может пойти. Его срок службы управляется вручную, и объект живет до тех пор, пока вы не достигнете delete.

Ваш вопрос опасно обременен предрассудками и предубеждениями. Лучше всего подойти к C++ с чистым умом и открытым отношением. Только так вы сможете оценить чудеса языка в полной мере.


Вот чистый и открытый подход: ли думать о 1) классы хранения (автоматические, статические, динамические), 2) срок службы объекта (область видимости, постоянный, ручной), 3) объект семантики (значение (копии) против ссылки (псевдонимы)), 4) классы RAII и однопользовательской ответственности.очистит ум а) стека/куча, б) указателей, с) операторами новых/удалить, d) деструкторов/Конструкторов копирования/назначения.

+0

Вы не можете полностью очистить свой разум от операторов присваивания, потому что даже когда вы получите все остальное, вы должны явно «по умолчанию» перемещать ctor и переместить назначение для своих классов семантики значений :-) –

+1

+1 для чистого и открытый подход, хотя он должен быть в более крупном шрифте, а не меньшем; -P – AJG85

+1

@SteveJessop: постоянный заказ, как всегда: как только вы поймете, почему вы можете игнорировать совет, безопасно игнорировать совет :-) (Хотя если вы не объявляете * ничего *, вы должны получить оптимальную семантику перемещения автоматически, не?) –

3

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

#include <memory> 
int main() { 

    while(...) { 
     std::unique_ptr<int> foobar = new int; 
    } // smart pointer foobar deletes the allocated int each iteration 

    return 0; 
} 
-2

Foobar указатель создается в стеке, но новый int создается в куче. В случае цикла while каждый раз, когда петли кода, foobar выпадает из области. Созданный int сохраняется в куче. На каждой итерации создается новый int, и указатель сбрасывается, что означает, что указатель больше не может получить доступ к любому из предыдущих int (s) в куче.

Кажется, что в каждом из предыдущих ответов, и даже в этом, недостает кучи, выпавшей из сферы видимости. Может быть, я неправильно использую терминологию, но я знаю, что в какой-то момент куча тоже сбрасывается. Это может произойти после того, как программа больше не работает или когда компьютер выключен, но я знаю, что это происходит.

Давайте рассмотрим этот вопрос с другой точки зрения. Я написал любое количество программ, которые утечки памяти. На протяжении всех лет я владел своим компьютером, я уверен, я пропустил более 2 гигабайт памяти. Мой компьютер имеет только 1 гигабайт памяти. Поэтому, если куча НИКОГДА не выпадает из области видимости, тогда мой компьютер имеет магическую память. Кто-нибудь из вас захочет объяснить, когда именно куча выпадает из сферы действия?

1

Здесь foobar является указателем int, занимающим память в стеке. Экземпляр int, который вы создаете динамически с new, отправляется в кучу. Когда foobar выходит за пределы области видимости, вы теряете ссылку на него, поэтому вы не можете удалить память, выделенную в куче.

Лучшим решением было бы:

while(--) 
{ 
    int foobar; 
}//it goes out of scope here. deleted from stack automatically!! 

Если вы все еще хотите использовать динамическое выделение, то сделать это:

while(--) 
{ 
    int* foobar=new int; 
    //do your work here! 
    delete foobar; //This deletes the heap memory allocated! 
    foobar=NULL; //avoid dangling pointer! :) 
} 
Смежные вопросы