Automatic Memory ManagementAutomatic Memory Management

Для автоматического управления памятью используется одна из служб, которые среда CLR предоставляет при управляемом выполнении.Automatic memory management is one of the services that the Common Language Runtime provides during Managed Execution. Сборщик мусора среды CLR управляет освобождением и выделением памяти для приложения.The Common Language Runtime's garbage collector manages the allocation and release of memory for an application. Для разработчиков это означает, что при разработке управляемого приложения не нужно писать код для управления памятью.For developers, this means that you do not have to write code to perform memory management tasks when you develop managed applications. Автоматическое управление памятью позволяет устранить распространенные проблемы, такие как не освобожденный по забывчивости объект, вызывающий утечку памяти, или попытки доступа к памяти для уже удаленного объекта.Automatic memory management can eliminate common problems, such as forgetting to free an object and causing a memory leak, or attempting to access memory for an object that has already been freed. В этом разделе описано, каким образом сборщик мусора выделяет и освобождает память.This section describes how the garbage collector allocates and releases memory.

Выделение памятиAllocating Memory

При инициализации нового процесса среда выполнения резервирует для него непрерывную область адресного пространства.When you initialize a new process, the runtime reserves a contiguous region of address space for the process. Это зарезервированное адресное пространство называется управляемой кучей.This reserved address space is called the managed heap. Эта управляемая куча содержит указатель адреса, с которого будет выделена память для следующего объекта в куче.The managed heap maintains a pointer to the address where the next object in the heap will be allocated. Изначально этот указатель устанавливается в базовый адрес управляемой кучи.Initially, this pointer is set to the managed heap's base address. Все ссылочные типы размещаются в управляемой куче.All reference types are allocated on the managed heap. Когда приложение создает первый ссылочный тип, память для него выделяется, начиная с базового адреса управляемой кучи.When an application creates the first reference type, memory is allocated for the type at the base address of the managed heap. При создании приложением следующего объекта сборщик мусора выделяет для него память в адресном пространстве, непосредственно следующем за первым объектом.When the application creates the next object, the garbage collector allocates memory for it in the address space immediately following the first object. Пока имеется доступное адресное пространство, сборщик мусора продолжает выделять пространство для новых объектов по этой схеме.As long as address space is available, the garbage collector continues to allocate space for new objects in this manner.

Выделение памяти из управляемой кучи происходит быстрее, чем неуправляемое выделение памяти.Allocating memory from the managed heap is faster than unmanaged memory allocation. Поскольку среда выполнения выделяет память для объекта путем добавления значения к указателю, это осуществляется почти так же быстро, как выделение памяти из стека.Because the runtime allocates memory for an object by adding a value to a pointer, it is almost as fast as allocating memory from the stack. Кроме того, поскольку выделяемые последовательно новые объекты и располагаются последовательно в управляемой куче, приложение может получать доступ к объектам очень быстро.In addition, because new objects that are allocated consecutively are stored contiguously in the managed heap, an application can access the objects very quickly.

Освобождение памятиReleasing Memory

Механизм оптимизации сборщика мусора определяет наилучшее время для выполнения сбора, основываясь на произведенных выделениях памяти.The garbage collector's optimizing engine determines the best time to perform a collection based on the allocations being made. Когда сборщик мусора выполняет очистку, он освобождает память, выделенную для объектов, которые больше не используются приложением.When the garbage collector performs a collection, it releases the memory for objects that are no longer being used by the application. Он определяет, какие объекты больше не используются, основываясь на корнях приложения.It determines which objects are no longer being used by examining the application's roots. Каждое приложение имеет набор корней.Every application has a set of roots. Каждый корень либо ссылается на объект, находящийся в управляемой куче, либо имеет значение NULL.Each root either refers to an object on the managed heap or is set to null. Корни приложения содержат статические поля, локальные переменные и параметры стека потока, а также регистры процессора.An application's roots include static fields, local variables and parameters on a thread's stack, and CPU registers. Сборщик мусора имеет доступ к списку активных корней, которые поддерживаются JIT-компилятором и средой выполнения.The garbage collector has access to the list of active roots that the just-in-time (JIT) compiler and the runtime maintain. С помощью этого списка он проверяет корни приложения и в процессе проверки создает граф, содержащий все объекты, к которым можно получить доступ из этих корней.Using this list, it examines an application's roots, and in the process creates a graph that contains all the objects that are reachable from the roots.

Объекты, не входящие в этот граф, являются недостижимыми из данных корней приложения.Objects that are not in the graph are unreachable from the application's roots. Сборщик мусора считает недостижимые объекты мусором и будет освобождать выделенную для них память.The garbage collector considers unreachable objects garbage and will release the memory allocated for them. В процессе очистки сборщик мусора проверяет управляемую кучу, отыскивая блоки адресного пространства, занятые недостижимыми объектами.During a collection, the garbage collector examines the managed heap, looking for the blocks of address space occupied by unreachable objects. При обнаружении недостижимого объекта он использует функцию копирования памяти для уплотнения достижимых объектов в памяти, освобождая блоки адресного пространства, выделенные под недостижимые объекты.As it discovers each unreachable object, it uses a memory-copying function to compact the reachable objects in memory, freeing up the blocks of address spaces allocated to unreachable objects. После уплотнения памяти, занимаемой достижимыми объектами, сборщик мусора вносит необходимые поправки в указатель, чтобы корни приложения указывали на новые расположения объектов.Once the memory for the reachable objects has been compacted, the garbage collector makes the necessary pointer corrections so that the application's roots point to the objects in their new locations. Он также устанавливает указатель управляемой кучи в положение после последнего достижимого объекта.It also positions the managed heap's pointer after the last reachable object. Обратите внимание, что память уплотняется, только если при очистке обнаруживается значительное число недостижимых объектов.Note that memory is compacted only if a collection discovers a significant number of unreachable objects. Если после сборки мусора все объекты в управляемой куче остаются на месте, то уплотнение памяти не требуется.If all the objects in the managed heap survive a collection, then there is no need for memory compaction.

Для повышения производительности среда выполнения выделяет память для больших объектов в отдельной куче.To improve performance, the runtime allocates memory for large objects in a separate heap. Сборщик мусора автоматически освобождает память, выделенную для больших объектов.The garbage collector automatically releases the memory for large objects. Однако для устранения перемещений в памяти больших объектов эта память не сжимается.However, to avoid moving large objects in memory, this memory is not compacted.

Поколения и производительностьGenerations and Performance

Для оптимизации производительности сборщика мусора управляемая куча делится на три поколения: 0, 1 и 2.To optimize the performance of the garbage collector, the managed heap is divided into three generations: 0, 1, and 2. Алгоритм сборки мусора в среде выполнения основан на ряде обобщений, к которым пришла программная индустрия в процессе экспериментов со схемами сборки мусора.The runtime's garbage collection algorithm is based on several generalizations that the computer software industry has discovered to be true by experimenting with garbage collection schemes. Во-первых, уплотнять память для части управляемой кучи быстрее, чем для всей кучи.First, it is faster to compact the memory for a portion of the managed heap than for the entire managed heap. Во-вторых, более новые объекты имеют меньшее время жизни, а более старые объекты имеют большее время жизни.Secondly, newer objects will have shorter lifetimes and older objects will have longer lifetimes. Наконец, более новые объекты теснее связаны друг с другом, и приложение обращается к ним приблизительно в одно и то же время.Lastly, newer objects tend to be related to each other and accessed by the application around the same time.

Сборщик мусора среды выполнения хранит новые объекты в поколении 0.The runtime's garbage collector stores new objects in generation 0. Уровень объектов, созданных на раннем этапе работы приложения и оставшихся после сборок мусора, повышается, и они сохраняются в поколении 1 и 2.Objects created early in the application's lifetime that survive collections are promoted and stored in generations 1 and 2. Процесс продвижения объекта по уровням описан далее в этом разделе.The process of object promotion is described later in this topic. Поскольку быстрее сжать часть управляемой кучи, чем всю кучу, эта схема позволяет сборщику мусора освобождать память в определенном поколении, а не освобождать память для всей кучи каждый раз при сборке мусора.Because it is faster to compact a portion of the managed heap than the entire heap, this scheme allows the garbage collector to release the memory in a specific generation rather than release the memory for the entire managed heap each time it performs a collection.

В действительности сборщик мусора выполняет очистку при заполнении поколения 0.In reality, the garbage collector performs a collection when generation 0 is full. Если приложение пытается создать новый объект, когда поколение 0 заполнено, сборщик мусора обнаруживает, что в поколении 0 не осталось свободного адресного пространства для объекта.If an application attempts to create a new object when generation 0 is full, the garbage collector discovers that there is no address space remaining in generation 0 to allocate for the object. Сборщик мусора выполняет сборку, пытаясь освободить для этого объекта адресное пространство в поколении 0.The garbage collector performs a collection in an attempt to free address space in generation 0 for the object. Сборщик мусора начинает проверять объекты в поколении 0, а не все объекты в управляемой куче.The garbage collector starts by examining the objects in generation 0 rather than all objects in the managed heap. Это наиболее эффективный подход, поскольку, как правило, новые объекты имеют меньшее время жизни, и можно ожидать, что многие из объектов в поколении 0 к моменту проведения сборки мусора уже не используются приложением.This is the most efficient approach, because new objects tend to have short lifetimes, and it is expected that many of the objects in generation 0 will no longer be in use by the application when a collection is performed. Кроме того, сборка мусора только в поколении 0 зачастую освобождает достаточно памяти для того, чтобы приложение могло продолжить создавать новые объекты.In addition, a collection of generation 0 alone often reclaims enough memory to allow the application to continue creating new objects.

После того как сборщик мусора выполнит освобождение для поколения 0, он уплотняет память для достижимых объектов, как описано ранее в разделе Освобождение памяти.After the garbage collector performs a collection of generation 0, it compacts the memory for the reachable objects as explained in Releasing Memory earlier in this topic. Затем сборщик мусора продвигает эти объекты и считает эту часть управляемой кучи поколением 1.The garbage collector then promotes these objects and considers this portion of the managed heap generation 1. Так как объекты, оставшиеся после сборки, обычно склонны к долгой жизни, имеет смысл продвинуть их в поколение более высокого уровня.Because objects that survive collections tend to have longer lifetimes, it makes sense to promote them to a higher generation. В результате сборщику мусора не обязательно выполнять повторную проверку объектов поколений 1 и 2 при каждой сборке мусора в поколении 0.As a result, the garbage collector does not have to reexamine the objects in generations 1 and 2 each time it performs a collection of generation 0.

После того как сборщик мусора выполнит первую сборку поколения 0 и продвинет доступные объекты в поколение 1, он считает оставшуюся часть управляемой кучи поколением 0.After the garbage collector performs its first collection of generation 0 and promotes the reachable objects to generation 1, it considers the remainder of the managed heap generation 0. Он продолжает размещать память для новых объектов в поколении 0, до тех пор пока поколение 0 не заполнится и необходимо будет провести следующую сборку.It continues to allocate memory for new objects in generation 0 until generation 0 is full and it is necessary to perform another collection. В этот момент оптимизатор сборщика мусора определяет, есть ли необходимость проверки объектов в более старых поколениях.At this point, the garbage collector's optimizing engine determines whether it is necessary to examine the objects in older generations. Например, если сборка поколения 0 не освобождает достаточно памяти, чтобы приложение могло успешно завершить создание объекта, сборщик мусора может выполнить сборку мусора поколения 1, а затем поколения 2.For example, if a collection of generation 0 does not reclaim enough memory for the application to successfully complete its attempt to create a new object, the garbage collector can perform a collection of generation 1, then generation 2. Если и это не действие не освободит достаточно памяти, сборщик мусора может выполнить сборку мусора поколений 2, 1, и 0.If this does not reclaim enough memory, the garbage collector can perform a collection of generations 2, 1, and 0. После каждой сборки сборщик мусора собирает доступные объекты в поколении 0 и продвигает их в поколение 1.After each collection, the garbage collector compacts the reachable objects in generation 0 and promotes them to generation 1. Объекты в поколении 1, оставшиеся после сборок, продвигаются в поколение 2.Objects in generation 1 that survive collections are promoted to generation 2. Поскольку сборщик мусора поддерживает только три поколения, объекты в поколении 2, оставшиеся после сборки, остаются в поколении 2 до тех пор, пока они не перестанут быть доступными в результате сборки мусора.Because the garbage collector supports only three generations, objects in generation 2 that survive a collection remain in generation 2 until they are determined to be unreachable in a future collection.

Освобождение памяти для неуправляемых ресурсовReleasing Memory for Unmanaged Resources

Для большинства объектов, созданных приложением, сборщик мусора автоматически выполнит необходимые задачи по управлению памятью.For the majority of the objects that your application creates, you can rely on the garbage collector to automatically perform the necessary memory management tasks. Однако для неуправляемых ресурсов требуется явная очистка.However, unmanaged resources require explicit cleanup. Основным типом неуправляемых ресурсов являются объекты, образующие упаковку для ресурсов операционной системы, такие как дескриптор файлов, дескриптор окна или сетевое подключение.The most common type of unmanaged resource is an object that wraps an operating system resource, such as a file handle, window handle, or network connection. Хотя сборщик мусора может отслеживать время жизни управляемого объекта, инкапсулирующего неуправляемые ресурсы, он не имеет определенных сведений о том, как освобождать эти ресурсы.Although the garbage collector is able to track the lifetime of a managed object that encapsulates an unmanaged resource, it does not have specific knowledge about how to clean up the resource. При создании объекта, который инкапсулирует неуправляемый ресурс, рекомендуется включить код для очистки неуправляемого ресурса в общий метод Dispose.When you create an object that encapsulates an unmanaged resource, it is recommended that you provide the necessary code to clean up the unmanaged resource in a public Dispose method. Метод Dispose позволяет явно освобождать память при завершении работы с объектом.By providing a Dispose method, you enable users of your object to explicitly free its memory when they are finished with the object. При использовании объекта, который инкапсулирует неуправляемый ресурс, следует помнить о методе Dispose и при необходимости вызывать его.When you use an object that encapsulates an unmanaged resource, you should be aware of Dispose and call it as necessary. Дополнительные сведения об освобождении неуправляемых ресурсов и пример шаблона для реализации метода Dispose см. в разделе Сборка мусора.For more information about cleaning up unmanaged resources and an example of a design pattern for implementing Dispose, see Garbage Collection.

См. также разделSee also