Memory management for C # value types and reference types

Source: Internet
Author: User
In this journal, let's focus on how to improve performance in the software development process. This is a deep-seated problem in software development or development, this article mainly from memory allocation and memory recovery two aspects, our software code writing process, how to calculate how to work. Here you can learn about the process and methods of memory management so that you will be aware of it and use it in future software development.

Value types include: Int,float,double,bool, struct, reference, variable representing object instance

Reference types include: classes and arrays; Comparison of special reference types string, object

In general: Value types are stored in the stack (not including value types contained in references, such as class value fields, reference fields in classes, elements of arrays are stored with references in the controlled heap), reference types are stored in the controlled heap, and why are controlled heaps, as discussed below.

Several concepts:

Virtual Memory: 32-bit computers with 4G of virtual memory per process.

Controlled Heap (managed heap): Who is under control? Of course it is a useless unit collector, or garbage collector. How to manage the following again?

Garbage collector: In addition to compressing the managed heap, updating the reference address, maintaining a list of information for the managed heap, and so on.

For storage of value types, let's look at the following code:

{

int age=20;

Double salary=2000;

}

The two variables defined above, int age, tell the compiler to allocate 4 bytes of memory space to store the age value, which is stored on the stack. The stack belongs to the advanced data structure, which stores data from the high address to the low address. The computer register holds a stack pointer that always points to the bottom-most free-space address of the stack, and when we define a value of type int, the stack pointer decrements the four-byte address, and when the variable is scoped, the stack pointer increments the corresponding four-byte address, which is just the stack pointer moving up and down. So the performance of the stack is quite high.

Take a look at the storage of the reference type, or look at the code first:

{

Customer Customera;

Customera=new Customer (); Assume that a customer instance occupies 32 bytes

}

The first line of the above code declares a customer reference, which is named Customera, allocates storage space on the stack for this reference, and the size of the storage space is 4 bytes because it stores only one reference, which points to the space address where the customer instance will be stored , note that at this point the Customera does not point to a specific space, it just allocates a space.

During the second line of execution, the. NET environment searches the managed heap, looking for the first unused, contiguous 32-byte space allocated to instances of the class, and sets the Customera to point to the top position of the space (the heap's space is low to high). When a reference variable is out of scope, the reference in the stack is invalid when the instance in the managed heap is still there until the garbage collector cleans it up.

Here the attentive reader may have some questions, is not the definition of reference type, the computer to search the entire heap, looking for large enough memory space to store objects? Will this be inefficient? What if there's not enough room for continuous space? This is going to be about "hosting." The heap is managed by the garbage collector, and. NET frees all objects that can be freed when the garbage collector executes, compresses other objects, and then combines all the free spaces together to the top of the heap, forming contiguous blocks, while updating references to other moving objects. If there is another object definition, you can quickly find the right space. So it seems that the managed heap works like a stack, where it accomplishes the allocation and recycling of space through a heap pointer.

It talks about the management process and the way of the memory space allocation in. NET, and then we talk about the memory recycling process. When it comes to resource cleanup, there are two concepts and three methods that have to be mentioned.

The two concepts are: managed and unmanaged resources.

Managed resources accept the management of the CLR (Common Language Runtime) of the. NET Framework, and unmanaged resources are not managed by it.

Three methods are: Finalize (), Dispose (), Close ().

Finalize () is the destructor method and clears the unmanaged resource.

Define the way in the class:

Public classname{

~classname ()

{

Clean up Unmanaged resources (such as closing files and database joins, etc.)

}

}

It is characterized by:

1. Operational uncertainties.

It is managed by the garbage collector, and this method is called when the garbage collector is working.

2. High performance overhead.

The garbage collector works as if the object executes the Finalize () method, it is placed in a special queue the first time the garbage collector executes, and the object is deleted when the second execution occurs.

3. Definition and invocation cannot be displayed, defined as a destructor method form.

Based on the above features, it is best not to execute the Finalize () method unless the class does need it or is combined with two other methods.

The Dispose () method clears all resources that need to be purged, including managed and unmanaged resources.

Defined as follows:

public void Dispose ()

{

Clean up resources (including managed and unmanaged resources) that should be cleaned up

System.GC.SuppressFinalize (this); This sentence is important and the reasons are explained below.

}

It is characterized by:

1. Any customer code should show that this method is called to free up resources.

2. For the 1th reason, a backup is generally done, and this backup is typically performed by a destructor.

3. The class that defines this method must inherit the IDisposable interface.

4. The syntax keyword using is equivalent to calling Dispose (), which is called by default when using the Dispose () method. Therefore, the use of the class to inherit the IDisposable interface.

The Dispose () method is flexible and is released immediately when resources are not needed. It is the final processing of the resource, and invoking it means that the object is eventually deleted.

The Close () method temporarily disposes of the state of the resource and may be used later. Generic handling of unmanaged resources.

Defined as follows:

Public Viod Close ()

{

Settings for the status of unmanaged resources, such as closing a file or database connection

}

It is characterized by:

The settings for the unmanaged resource state are typically closed files or database connections.


Here is a comprehensive and classic example, using the code to demonstrate the role of each part: (For the sake of trouble, this example is invented from the Internet, as long as the problem can be explained, you say.) Here should thank the code originator, thank him for writing such a classic and understandable code, we benefit! )


public class ResourceHolder:System.IDisposable

{

public void Dispose ()

{

Dispose (TRUE);

System.GC.SuppressFinalize (this);

The previous line of code is to prevent the garbage collector from invoking a destructor in this class

"~resourceholder ()"

Why should it be prevented? Because if the user remembers to call the Dispose () method, then

The "garbage collector" has no need to "superfluous" the "unmanaged Resources" again.

If the user does not remember the call, let the "garbage collector" help us to "superfluous" it ^_^

You do not understand what I said above does not matter, below I also have a more detailed explanation!

}


protected virtual void Dispose (bool disposing)

{

if (disposing)

{

This is the user code snippet that cleans up the managed resources.

}

This is the user code snippet that cleans up unmanaged resources. Here is the actual execution code of the destructor method, in order to avoid the customer code forgetting to display the call to the Dispose () method, the backup made.

}


~resourceholder ()

{

Dispose (FALSE); This is the cleanup of unmanaged resources.

}

}


If you do not understand the above code, must carefully read the following explanations, very classic, do not look will regret yo.

Here, we have to be clear that the user is required to call the method Dispose () instead of the method Dispose (bool), however, the method that actually performs the release work here is not Dispose (), but Dispose (bool)! Why not? Look closely at the code, in Dispose (), call Dispose (true), and the argument is "true" when the function is to clean up all the managed and unmanaged resources; You remember before I said, "The use of destructors is used to release unmanaged resources", So since Dispose () can do the work of releasing unmanaged resources, what do you do with the destructor method? In fact, the function of the destructor is only a "backup"!

Why is it?

Lattice says that any class that executes the interface "IDisposable" will have to invoke the Dispose () method of the class as long as the programmer uses the class's object instance in the code, and the unmanaged resource must be freed if the class contains use of unmanaged resources! Unfortunately, if the code that frees the unmanaged resource is placed in the destructor (the example above corresponds to "~resourceholder ()"), then it is impossible for the programmer to invoke the release code (because the destructor cannot be called by the user, but only by the system, which is called the "garbage Collector"). So you should know why the "user code snippet to clean unmanaged resources" in the example above is in Dispose (bool), not ~resourceholder ()! Unfortunately, not all programmers are always careful to call the Dispose () method, in case the programmer forgets to call this method, the managed resource is certainly no problem, sooner or later there will be a "garbage collector" to recycle (just a little later), then unmanaged resources? It is not controlled by the CLR! Is it that the unmanaged resources it occupies will never be released? Of course not! We also have "destructor"! If you forget to call Dispose (), the garbage collector also calls the Destructor method to release the unmanaged Resources! (Say a little more nonsense, if the programmer remembers calling Dispose (), then the Code "System.GC.SuppressFinalize (this);" You can prevent the garbage collector from calling the destructor, so that you don't have to release the unmanaged resource more than once, so we're not afraid of programmers forgetting to call the Dispose () method.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.