This article has been migrated to: http://cpp.winxgui.com/cn:story-of-c-memory-management-innovation
C ++ memory management revolution
Xu Shiwei
2005-7-16Keywords: Memory Management Garbage Collector memory configurator reference count Keyword: Memory manage, memory recycler, Allocator, reference count
IntroductionMemory Management in C/C ++ has undergone several changes, but it has not yet matured. These changes mainly include: 1. From malloc/free to new/Delete. This revolution is the product of the rise of OOP technology. C ++ is a strong type language. The main achievement of new/delete is to strengthen the concept of type and reduce the need for forced type conversion. However, from the perspective of memory management, there is not much breakthrough in this change. 2. From New/Delete to memory configurator (Allocator ). Since STL was incorporated into the C ++ standard library, the C ++ world has undergone tremendous changes. From the perspective of memory management, allocator is also a breakthrough in C ++ memory management. Note that the memory of all STL components is allocated from allocator. In other words, STL does not recommend using new/delete for memory management, but allocator.
However, the Allocator of STL does not cause a huge change in the memory management of the C ++ language. Few people except STL use Allocator, or even realize the importance of allocator. Therefore, C ++ programmers are still using new/delete for tedious memory allocation/release processes while using STL.
There are two main reasons. First, with the introduction of Allocator, the STL designer is mainly designed to separate memory management from the implementation of containers, so that STL users can choose from memory management algorithms. Designers themselves may not be aware of the importance of allocator. Second, Allocator itself focuses only on efficiency, but not on the change of memory management concepts for C ++ language users.
In short, in my opinion, introducing Allocator in STL is a great thing. However, this change has been neglected and has not been implemented. Of course, this is also related to defects of STL Allocator itself. This article will discuss how to implement the STL Allocator idea and make appropriate improvements to it in order to make a revolutionary breakthrough in the concept of C ++ memory management, eliminate the traditional New/delete memory management method [1].
Garbage CollectorAlmost all currently popular garbage collectors tend to treat users as a dummies, hoping that they can be used well without having to fully understand memory management. It should be said that they have basically done the same (although users sometimes have such troubles, but the overall situation has indeed been greatly improved ). However, I do not quite agree with this design concept. First of all, you can work in a language that provides a garbage collector without being troubled by the garbage collector. It is already a great thing. They are definitely very smart people, not dummies. They understand how the garbage collector works, select it and let it work for them, just because there are more important things waiting for them to do. When necessary, they need a way to control the Garbage Collector so that it can work as desired. Therefore, the main point of the garbage collector design is to free users from the cumbersome memory management, so that they can devote all their energy to their own business logic, instead of making the garbage collector look dumb. Second, when a fully automated garbage collector is used and the memory collection time is unclear, there is a great deal of uncertainty in the working process of the garbage collector, which brings troubles to users. For example, C # becomes more prominent when calling uncontrolled Code (for example, calling Win32 API. When you are not careful, it is possible that the Win32 API is still using a piece of memory, and the garbage collector has recycled it. When carefully avoiding these traps, this feeling is actually a bit similar to that of C/C ++ programmers who regret that the language does not have a garbage collector. Therefore, the ideal situation is that the memory manager provides the garbage collection capability, but it only provides this capability,
You can control the garbage collection process by yourself. In addition, you can force release a piece of memory instead of waiting for the garbage collection process to decide when to recycle the memory.. For the customer, he has the right to control everything, but if he does neglect, the garbage collector can escort him. Is it possible to introduce the Garbage Collector into C ++? I think it is quite difficult if we try to provide a fully automated garbage collector. We can see that Microsoft still cannot do this well [2]. Perhaps we need to change our mindset: A semi-automatic Garbage Collector may be able to get along with C ++?
First recognized AllocatorGenerally, allacator is a class that provides services related to memory management (which may include memory allocation, release, automatic recovery, and other capabilities. For example, we can use the malloc/free provided by C to immediately provide an allocator implementation: Class
Simplealloc{Public:
//
Note the parameters provided here
Fndestroy
For those with garbage collection capabilities
Allocator
Required.
Void* Alloc (
Size_tCB,
FndestructorFndestroy = NULL ){
ReturnMalloc (CB );}
//
Note that there are seemingly redundant parameters.
CB
This is completely for the purpose of providing
Allocator
The specifications must be consistent.
VoidFree (
Void* Data,
Size_tCB) {free (data) ;}}; with Allocator, we can apply for memory, but we cannot use it to create a C ++ object. To facilitate the creation of C ++ objects, we provide new operations. The prototype is roughly as follows:
Template<Class
Type, Class
Alloctype>
Type* New (
Alloctype& Alloc );
//
Similar
New Type
Template<Class
Type, Class
Argtype1, Class
Alloctype>
Type* New (
Argtype1Arg1,
Alloctype& Alloc );
//
Similar
New Type (arg1)
Template<Class
Type, Class
Alloctype>
Type* Newarray (
Size_tCount,
Alloctype& Alloc );
//
Similar
New Type [count]With these helper functions, we can create objects. Example:
SimpleallocAlloc;
Int* Intarray = newarray <
Int> (Count, alloc );
Myclass* OBJ = new <
Myclass> (Alloc );
Myclass* Objwitharg = new <
Myclass> (Arg1, alloc );
Myclass* Objarray = newarray <
Myclass> (Count, alloc); although we use simplealloc to create an object, we must note that these new operations are effective for all Allocator operations. If you are concerned about the code of the new function, don't worry. Now we can see it right away. But first, we will continue to discuss allocator.
Conceptual changes caused by AllocatorWith Allocator, you can see that it is different from the traditional New/delete concept in C ++. This mainly includes the following points: 1. each class (or algorithm) has its own memory management mechanism that is best suited to it. It does not use a global new/delete mechanism in the traditional way of C ++. Maybe you will say that C ++ does not allow a class to define its own new and delete? Yes, C ++ does support class definition of its own new/delete, but note that its concept is completely different from allocator. I don't think it is a good job of C ++. On the contrary, it is misleading.
Because it does not depend on the class itself, but on the person who uses the class. A class does not need to care about how it is created, not to be assumed. It needs to care about how its own class members are created and how all components involved in its algorithms (you can think of classes as an algorithm set) are created. This is the concept of allocator.
Allows various Allocator instances to create different instances of the same class. These instances may even work together and collaborate with each other. From the STL perspective, this is the most normal thing.
2. It is important to create management objects by allocator to avoid using new/delete in your code. If possible, you can use Allocator as a template parameter like STL without binding a specific memory manager. However, it doesn't matter if your algorithm depends on a specific implementation function of allocator. Your goal is not to replace Allocator, isn't it? It is important to use Allocator, which brings you benefits in memory management. However, we should see that all kinds of Allocator implemented by STL are mainly based on mempool technology, except for the simplest implementation of malloc/free. The goal of this technology is not to allow memory users to manage memory more conveniently and effectively, but to focus more on the time performance of memory allocation. To free C ++ programmers from memory management, we need to implement new alloctor and new breakthroughs!
New Perspective: Allocator with garbage collection capabilityYes, one approach I imagine is to implement the STL Allocator concept and provide various Allocator with specific memory management capabilities (such as garbage collection. This allows the C ++ community to broadly accept and benefit from the Allocator concept. C ++ programmers often abandon the traditional New/delete and let them exit the stage of history. Next I will implement two specific Allocator (both original ). I believe they will make you feel refreshed, so you can't help but think: Oh, originally in C ++, I can also perform memory management like this. Of course, my biggest hope is that these two Allocator can play a very important role, so that everyone can be aware of the importance of Allocator and more Allocator with various capabilities, free C ++ programmers from the long-lasting suffering (which may be the greatest suffering [3]). Both Allocator have a certain degree of garbage collection capability. However, they have different ideas. We will discuss them in two topics.
Auxiliary New ProcessWe can finally start to discuss the implementation of the new function mentioned above. Taking new without parameters as an example, its code is as follows, which may not be as complicated as you think :#
Include<New>
Template<Class
Type, Class
Alloctype>
Inline type* New (
Alloctype& Alloc ){
Void* OBJ = alloc. alloc (
Sizeof(
Type),
Destructortraits<
Type>:: Destruct );
ReturnNew (OBJ)
Type;} Where
DestructortraitsIs a type-based
Type[4] extraction Generator for destructor. It looks like this:
Template<Class
Type>
Struct
Destructortraits{
Static
VoidDestruct (
Void* Pthis ){((
Type*) Pthis)-> ~
Type() ;}}; In this way, you can use the following code to generate an object:
Myclassa* OBJ = new <
Myclassa> (Alloc );
Myclassb* OBJ = new <
Myclassb> (Alloc );
Special reminder: Here, the new function is compiled and passed in VC ++ 6.0, but the Execution Code generated has a serious bug. If you only use the new class object, there is no problem, but after the new class object, it seems that
Myclassa,
MyclassbThe two are confused. To support VC ++ 6.0, you need to adjust the new here (for details about this point, refer to: VC ++ 6.0 Tips ).
COM technology[5]And Memory ManagementAt the end of this short article, I suddenly thought of some of my thoughts on using COM technology for a long time. These ideas are closely related to memory management. Therefore, I would like to make a statement on this issue. From the iunknown interface of COM, it mainly focuses on two problems: QueryInterface and reference count (addref/release ). COM components are sensitive to information shielding, and users have limited understanding of components, which makes it possible to upgrade and expand components. QueryInterface is a good concept that needs to be carried forward. The reference count of COM focuses on the lifetime maintenance of components. In other words, it is about how components are destroyed. It is true that the destruction of component objects is the key to memory management. Whether it is com reference counting or garbage collection technology, it is necessary to solve the problem of object destruction. The focus of both is not the same. com reference count focuses more on "ensure that components are not destroyed in advance and ensure the security of component access ", the garbage collector is concerned with "no matter how to ensure that the component is eventually destroyed, there is no memory leakage ". In COM, it is too important to ensure the security of Component Access (avoid unauthorized access), so that it does not even increase the programmer's memory management burden. Therefore, it is normal for a com program to have a memory leak, which is usually a large part of Memory leakage. Even worse, you cannot even have a very simple and effective way to determine which code is causing this leakage. Because all the customers of the component are equal, any customer code problems will lead to memory leakage. When I first came into contact with COM technology, I held a positive attitude towards reference counting. However, as the Department gradually stepped up the use of COM technology, I began to get confused in year 45. Everything is not as expected. How much extra cost does this reference count cost! This confusion and thinking may be the cause of this article and subsequent content.
[1] if you have any different views on this article, or have any need to discuss with me, welcome to contact: xushiweizh@gmail.com. [2] Microsoft's financial strength is obvious to all. However, its attempt to control code in VC ++ does not seem to have been successful. In addition, Microsoft cannot integrate the Classic C ++ uncontrolled code with the controlled code. I don't think we should have gotten into this dead end. [3] Of course, another fatal injury to C ++ is that there is no standard graphics/interface library. However, after all, there are various interface libraries supported. However, memory management seems to be an inherent defect of C ++ and has not been taken seriously. [4] extraction, English traits, is a model of special technology application of C ++ templates, and is widely used by libraries such as STL and boost. [5] COM technology runs through all Microsoft products and brings great success. To understand COM technology, there are many good books, such as "com essence theory" and "COM technology insider.