Customize new and delete

Source: Internet
Author: User

New and delete are basic interfaces for memory allocation and release in C ++,ProgramThe management of memory by Members relies on these two interfaces.

Since the C ++ compiler already provides the new and delete interfaces, why do we recreate the new and delete interfaces.

This raises the first question,Under what circumstances do we need to re-customize new and delete?(It must be when the new and delete provided by the compiler meet the requirements)

1. Used to Detect application errors

During programming, "overruns" (after the end of the allocated block) or "underruns" (before the start point of the allocated block) may occur ). if we define an operator news, we can overallocate the memory and place the specified byte patterns with extra space (before or after the customer's block. operator deteles can check whether the above signature has not changed. If not, it indicates that overrun and underrun occurred at a certain time point in the allocation area. At this time, operator Delete can record this fact.

2. To improve efficiency

Various applications have different requirements for the Memory Manager. The operator news and operator deletes provided by the compiler take a moderate approach to satisfy various allocation patterns, their work is moderately good for everyone, but they do not have the best performance for any specific needs. if you have a deep understanding of the dynamic memory usage type of the program and customize operator new and operaotr Delete, the performance can be better than the default.

3. to collect statistical data during use

Before making operator new and operator Delete, we must understand how the program uses dynamic memory. How is the size distribution of allocated blocks? What is the life cycle distribution? They tend to be allocated and returned in FIFO or LIFO or random order. To collect this information, we customize operator new and operator Delete.

4. To increase the allocation and return speed

The generic distribution is often slower than the custom distribution, especially when the custom distribution is designed for a specific type of object. of course, before proceeding to the conclusion that "operator new" and "operator Delete" have the value of accelerating the program speed, we must analyze the program to confirm that the program bottleneck does occur on those memory functions.

5. To reduce extra space overhead caused by default Memory Manager

Generic splitters often use more memory, especially when allocating small objects, which may lead to a waste of resources because they often introduce some additional overhead on each allocation block. the Allocator developed for small objects can eliminate such extra overhead.

6. To make up for the non-optimal position in the default allocation

In the X86 architecture, doubles is the fastest to access, if they are all 8-byte homogeneous. however, operator news provided by the compiler does not guarantee that 8-bytes is used for the dynamically allocated doubles. in this case, the default operator new is replaced with an 8-byte homogeneous guaranteed version, which can greatly improve the program efficiency.

7. To make related objects into a cluster

If we know that a specific data structure is often used together, and we want to minimize the frequency of "Memory Page errors" when processing the data, we can create another heap for some data structures so that they can be concentrated on as few memory pages as possible.

8. To obtain nontraditional Behaviors

Sometimes we need operator news and deletes to do something that the compiler does not. for example, allocate and return the blocks in the shared memory, but the only function that can manage the memory is the c API function. Therefore, write a customized new and delete, add a C ++ coat Based on the c api.

Now that we know the time to customize new and delete, we have to start to customize new and delete.

Before customizing new and delete, we need to understand the new and delete mechanisms provided by the compiler, which is equivalent to looking at the current wheel before creating our own wheel and referring to the existing implementation.

The specific implementation is not described in detail here.New-handler Processing Mechanism.

New provided by the compiler, with insufficient memory, provides its own processing mechanism. before operator new throws an exception to reflect an unfulfilled memory requirement, it calls an error processing function specified by the customer, new-handler.

When we customize new and delete, we also need to provide corresponding processing mechanisms. We can use set_new_handler to specify our own error processing functions. The specific usage is as follows:

 1   Namespace  STD {  2 Typedef Void (*New_handler )();  3 New_handler set_new_handler (new_handler P) Throw  ();  4   }  5   6   Void  Outofmem ()  7   {  8 STD: cerr < "  Unable to satisfy request for memory \ n "  ;  9   STD: Abort ();  10   }  11   Int  Main ()  12   {  13   STD: set_new_handler (outofmem );  14       Int * Pbigdataarray = New   Int [ 000000000l  ];  15   ...  16 }

The key is how to implement the error processing function to better meet our needs.A well-designed new-handler function must do the following::

1. Make more memory available.

2. install another new-handler.

3. Remove New-handler.

4. Throw an exception of bad_alloc (or derived from bad_alloc.

5. Do not return. usually call abort or exit.

Although we can use set_new_handler to specify an error handler to handle memory allocation failures in different ways.

However, every call to set_new_handler is a global error handling function. When we need to set different error handling functions for objects of different classes, we need to call set_new_handler multiple times.

In addition, to ensure that the default error processing function is called, we must save the default error processing function before setting different error processing functions, to reset the original status.

How can we ensure that the memory allocation fails to be processed in different ways? The memory processing method depends on the object type, that is, the class exclusive New-handlers.

The following describes how to implement the class-specific new-handler.

Implementation ideas:

Each class is provided with its own set_new_handler and operator new. Specifically, set_new_handler allows you to specify the New-handler exclusive to the class,Operator new makes sure that the Global New-handler is replaced with the class-specific new-handler when the class Object Memory is allocated.

Operator new does the following:

1. Call the standard set_new_handler to install the dedicated new-handler of the class as global new-handler.

2. Call global operator new to execute the actual memory allocation. If the allocation fails, global operator new will call the dedicated new-handler of the class.

If the global operator new cannot allocate enough memory, a bad_alloc exception will be thrown.In this case, you need to ensure that the original New-handler can be restored, so the new-handler is managed by the object.

The restoration process of new-handler is completed by the class destructor. When the object is out of scope, it calls the destructor to restore the original New-handler.

 1   Class  Newhandlerholder {  2  Public  :  3       Explicit  Newhandlerholder (STD: new_handler NH)  4   : Handler (NH ){}  5 ~ Newhandlerholder ()  6   {  7   STD: set_new_handler (handler );  8   }  9  Private  :  10   STD: new_handler handler;  11 Newhandlerholder ( Const Newhandlerholder & );  12 Newhandlerholder & Operator = ( Const Newhandlerholder & );  13   };  14 Template <typename T>15   Class  Newhandlersupport {  16   Public  :  17       Static STD: new_handler set_new_handler (STD: new_handler P) Throw  ();  18       Static   Void * Operator   New (STD: size_t size)Throw  (STD: bad_alloc );  19   ...  20   Private  :  21       Static  STD: new_handler currenthandler;  22   };  23 Template <typename T> 24   STD: new_handler  25 Newhandlersupport <t >:: set_new_handler (STD: new_handler P) Throw  ()  26   {  27 STD: new_handler oldhandler = Currenthandler;  28 Currenthandler = P;  29       Return  Oldhandler;  30   }  31   32 Template <typename T> 33   Void * Newhandlersupport <t> :: Operator   New  (STD: size_t size)  34   {  35   Newhandlerholder H (STD: set_new_handler (currenthandler ));  36       Return :: Operator   New  (Size );  37  }  38   39 Template <typename T> 40 STD: new_handler newhandlersupport <t >:: currenthandler = 0  ;  41   42   Class Widget: Public Newhandlersupport <widget> {  43   ...  44 };

After learning about the new and delete implementation mechanisms of the compiler, we need to start customizing new and delete.

In the customization process, in order to ensure the consistency of the customized new and delete, it is necessary to ensure that it complies with some rules.

1. Operator new must return the correct value. When the memory is insufficient, the new-handling function must be called.

2. Operator new must be prepared to deal with zero memory requirements.

In operator new provided by the compiler, even if the customer requires 0 bytes, operator new must return a valid pointer. Custom new must also properly handle the 0byte requirement.

3. Operator new must be used to call the base class operator new in the derived class.

The solution is to change the calling behavior of memory application errors to the standard operator new.

1 Void* Base ::Operator New(STD: size_t size)Throw(STD: bad_alloc)2 {3If(Size! =Sizeof(Base ))4Return::Operator New(Size );5 ...6}

4. Operator delete must ensure that "deleting null pointers is always safe ".

1   Void Base :: Operator Delete ( Void * Rawmemory, STD: size_t) Throw  ()  2   {  3       If (Rawmemory = 0 ) Return  ;  4       If (Size! =Sizeof  (Base ))  5   {  6 :: Operator  Delete (rawmemory );  7           Return  ;  8   }  9   ...  10       Return  ; 11 }

In addition, pay attention to the customization of new and deleteThread security issues.

Because heap is a global resource that can be modified, the multi-threaded system is flooded with race conditions (race speed status) for accessing such resources.

 

 

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.