c # memory management

In .net memory resources it can be divided into managed resources and unmanaged resources . Managed by the CLR resource management, unmanaged resources are not.

 

1, managed resources

Managed resources are stored in the "stack" and "managed heap."

 "Examples of local variables as a value type" and "instance of the reference type reference " will be stored on the stack.

"Examples of the type of value as a member of the class" and "instance of a reference type" will be stored on the heap.

 

1.1 Stack

Stack also known as thread stack space is relatively small, the latter is advanced out of the structure, the memory is filled by the address high to low.

A stack pointer to the next available space of the stack, the stack when there is a variable, a pointer to the address of a mobile lower, when the variable stack pointer is returned to a high address.

public static void Main()
{    
    int n = 1;    
    char c = 'a';
}

In the above code example, assume that the address from the 2000 start. Code beginning Main, the first to enter the variable n, because it is an integer 4 bytes, four bytes down pointer, the value of a variable n stored address 1997 to 2000.

The next line of code, character variable c is allocated two bytes of space, down two byte pointer, the value of the variable c 'a' stored addresses 1995 to 1996.

The last execution in brackets to the right of the Main function, execution ends, delete the value num and c. To move the pointer 2 bytes, the value of c to delete, move and then 4 bytes, the value of the num deleted.

Since the stack memory is contiguous, and only come from or into the top of the stack, there is no need for GC.

 

 1.2, heap

 The heap is managed heap short, it is managed by the CLR. It is the program is running, CLR application of a memory, the memory space is part of the process belongs to.

This space can be divided into:

1. the GC heap : 0,1,2 divided into three regions on behalf of, the greater the generation of the larger space, wherein the large object heap (large object heap) is a part of the stack 2 generations.

2. several application domains: the top has a respective loading heap (heap Loader) , is loaded on the heap memory of the method table (Method, the Table) , a static field stored thereon, all the functions, the type of substrate, etc. to achieve the interface. GC heap load without affecting its life cycle to create a program to uninstall domain.

 GC of three generations of recovery mechanisms: the newly created object is generation 0, when generation 0 is full, will trigger garbage collection, recycling will not become the first generation. So, when the generation recovered, he left to become the second generation.

 Large Object Heap : more than 85KB instance will be stored in the large object heap.

 Examples of the stack layout is as follows:

 

Sync block index (index Block Synchronization) : sync block index, also called the object header pointer, the address of an object located -4 to 0 bytes (32-bit type for example).

Index sync block synchronization thread used to judge the object is used or unused.

When there is a thread to operate on an object, check the value of the synchronization block index, if a value representing idle, will operate.

Then the sync blocks in the array increases in a new CLR sync blocks, the index value is written to this block sync block's index value, which represents occupied.

Thread exhausted, he gave back to the index value represents the unused value.

 

The method table pointer : a pointer to the method table type object.

Type of object is loading assemblies loaded in the heap created.

Object stores the type static fields and method table, is shared by all instances of that type.

The method table includes all functions, including static and non-static function function.

 

 

2, unmanaged resources

非托管资源是不受CLR管理的资源,最常见的非托管资源是包装操作系统资源的对象,例如文件、网络连接、数据库连接等。

C#提供Object.Finalize函数在GC时调用来释放这类资源,这个函数默认是空的,不过Object.Finalize是无法重载的,它是根据类的析构函数自动生成的,因此要将释放非托管资源的代码写在析构函数里。

 

说下GC调用Finalize的流程:

new一个包含Finalize函数的对象,开辟内存后,指向它的指针会被存放到终结列表Finalization List

垃圾回收时,被当作垃圾的对象如果同时存在于终结列表里,就会将该对象从终结列表中移除,并存入终结可达列表(F-reachable List)。并且这些对象变为可达,不会被GC回收,即表示这些对象提升了一代。

该队列中的对象都是可达的,并需要执行Finalize函数。执行Finalize函数是由一个高优先级的CLR线程进行的,执行完毕后,会将对象的指针从Freachable Queue中移除。

当再次进行垃圾回收时,原终结可达列表里的对象经过处理都变为不可达对象,只有当这一代内存不足时才会对对象进行垃圾回收,这些对象内存才会真正释放掉。所以含有Finalize函数的对象最少要经过两次垃圾回收才会被真正释放。

 

因为非托管资源比较有限,等GC调用Finalize释放,会让非托管资源处于不必要的空闲状态,影响性能。因此定义了一个IDispose接口,用于手动释放非托管资源。

在一个包含非托管资源的类中,关于资源释放的标准做法是:

① 继承IDisposable接口;

② 实现Dispose()方法,在其中释放托管资源和非托管资源,并将对象本身从垃圾回收器中移除(垃圾回收器不在回收此资源);

③ 实现类析构函数,在其中释放非托管资源。

 

提一下,继承了IDispose接口的类可以使用using,当超出作用域后,系统会自动调用Dispose函数。

 

Guess you like

Origin www.cnblogs.com/pj2933/p/10927014.html