Reading Notes Objective c ++ Item 50 it makes sense to know when to replace new and delete, too tiveitem

Source: Internet
Author: User

Reading Notes Objective c ++ Item 50 it makes sense to know when to replace new and delete, too tiveitem
1. Three common reasons for customizing new and delete

Let's first review the basic principles. Why do people want to replace the operator new and operator delete versions provided by the compiler at the beginning? There are three common causes:

  • To detect memory usage errors. Memory leakage may occur when the new memory cannot be deleted successfully. When you use a delete statement more than once in the new memory, undefined behaviors are generated. If operator new holds a memory allocation list and operator delete removes the address from the list, it is easy to detect this usage error. Similarly, different types of programming errors can result in overrun (overrun) or underrun) (write data before the memory block is allocated ). The custom operator new can allocate additional memory blocks, so there is space before and after the customer applies for memory to store the known byte mode ("signature signatures "). Operato delete can check whether the signature has changed. If it changes, overrun orunderrun may occur during the lifecycle of the memory block allocated, operator delete records this fact and records the value of the violation pointer.
  • To improve efficiency. The operator new and operator delete versions provided by the compiler are available to the public. They must be used by long-running programs (such as web server) and can also be used by programs whose execution time is less than 1 second. They must process requests for large memory blocks, small memory blocks, and mixed memory blocks. They must adapt to different memory allocation modes, from providing dynamic allocation of memory blocks for continuously running programs to allocating and releasing memory blocks that provide constant sizes for a large number of transient objects. They must consider the issue of memory fragmentation. If you do not check the memory fragmentation, memory requests may fail due to the fact that the memory is sufficient but distributed in different small memory blocks.

Considering the different requirements in memory management, it is not surprising that the operator new and operator delete in the compiler version provide you with a popular memory allocation policy. They can work well for everyone, but they are not optimal. If you have a good understanding of the dynamic memory usage mode of the program, you will find that the user-defined version of operator new and operator delete will be better than the default version. "Better than" means they run faster-sometimes the speed increases by an order of magnitude and they use less memory-up to 50% less memory. For some applications, the default operator new and operator delete versions can be easily replaced, but the performance can be greatly improved.

  • To collect statistics on memory usage. Before moving along the custom new and delete paths, it is very clever to collect information about how your software uses dynamically allocated memory. How is the size of the memory allocation block distributed? How is the lifecycle of a memory block distributed? Does memory allocation and release use the FIFO (first-in-first-out) sequence or the LIFO (later-in-first-out) sequence? Or sometimes it is closer to a random order? Does the memory usage change from time to time? For example, does your software have different memory allocation and release modes in different stages of execution? What is the maximum memory size that can be dynamically allocated at a time? The custom versions of operator new and operator delete make it easy to collect this information.
2. Alignment in custom operator new

In terms of concept, it is very easy to implement a custom operator new. For example, we can quickly implement a global operator new, which can easily detect out-of-boundary memory. It also has many small errors, but we will worry about them later.

 1 static const int signature = 0xDEADBEEF; 2  3 typedef unsigned char Byte; 4 // this code has several flaws — see below 5 void* operator new(std::size_t size) throw(std::bad_alloc) 6 { 7  8 using namespace std; 9 size_t realSize = size + 2 * sizeof(int);             // increase size of request so 210 // signatures will also fit inside11 12 void *pMem = malloc(realSize);   // call malloc to get the actual13 14  15 16 if (!pMem) throw bad_alloc();                                                          // memory17 18 // write signature into first and last parts of the memory              19 20 *(static_cast<int*>(pMem)) = signature;                                        21 22 *(reinterpret_cast<int*>(static_cast<Byte*>(pMem)+realSize-sizeof(int))) =          23 24 signature;                                                                                       25 26 // return a pointer to the memory just past the first signature       27 28 return static_cast<Byte*>(pMem) + sizeof(int);                             29 30 }      

Most of the problems with this operator new are because it does not conform to the C ++ convention. For example, Item 51 explains that all operator new should contain a loop that repeatedly calls the new-handling function, but this function does not. However, because there is an explanation in Item51, We will ignore it here. I want to pay attention to a more subtle problem:Alignment (Alignment).

For many computer architectures, when replacing specific types of data in the memory, it needs to be performed on specific types of addresses. For example, an architecture may require that the starting address of the pointer be an integer multiple of 4 (that is, 4-byte alignment) or the start address of the double type must be an integer multiple of 8 (that is, 8-byte alignment ). Failure to comply with this constraint will cause hardware exceptions during runtime. Other architectures may be more loose, that is, better performance if alignment is satisfied. For example, in intel X86 architecture, double can be aligned on any byte boundary, but if they are 8-byte aligned, access to them will be significantly faster.

Operator new and alignment are related, because C ++ requires that all pointers returned by operator new be properly aligned, and malloc works under the same requirements, therefore, it is safe for operator new to return the pointer from malloc. However, in the above operator new, we did not return the pointer from malloc, And we returned the pointer from malloc plus the offset of the int size. This is not guaranteed in terms of security! If the customer calls operator new to obtain enough memory for the double (or if we implement operator new [], apply for memory for the double array ), in addition, we work on a machine where the int size is 4 bytes but the double size requires 8-byte alignment. We may return a pointer with no proper alignment. This may cause program crash. Or it only slows down the program running. No matter what the result is, it is not what we want.

3. Generally, you do not need to customize new and delete

Because of the existence of details such as alignment, when programmers concentrate on completing other tasks, ignoring these details will cause various problems to be thrown out, this allows you to differentiate Professional-level memory managers. It is very easy to implement a Working Memory Manager. It is very difficult to achieve a good job. As a general rule, I suggest you do not try unless necessary.

3.1 use the default version and commercial products

In many cases, you do not have. Some compiler memory management functions have the function of controlling debugging and logging. A quick glance at your compiler documentation may eliminate your own idea of implementing New and delete. In many platforms, commercial products can replace the memory management functions provided by the compiler. Their enhanced features and improved performance can benefit you. All you need to do is relink (if you have to buy this product .)

3.2 use open source memory manager

Another option is open-source memory manager. You can find such a manager on many platforms, so you can download and try it. One open-source memory distributor comes from the Boost Pool Library (Item 55 ). The memory distributor provided by this Pool library is very helpful for user-defined memory management: that is, when a large number of small objects need to be allocated. Many C ++ books, including early versions of this book, show the source code of a high-performance small object memory distributor, but they usually ignore some details, such as portability, for alignment considerations, thread security and so on. The source code provided by the real library is more robust. Even if you decide to implement your own new and delete, you can take a look at these open-source versions to gain insight into the details that are easy to ignore, these details differentiate "basic work" from "real work. (Since alignment is such a detail, note that TR1 is very valuable, including support for specific types of alignment .)

4. Summary of the significance of using custom versions new and delete

The topic of this clause is to let you know under what circumstances it makes sense to replace the new and delete versions of the default version, whether in the global scope or within the scope of the class. Let's make a summary.

  • Detects memory usage errors.
  • Collects statistics on the use of dynamically allocated memory.
  • Increase the speed of memory allocation and release. Generally, the distribution provided to the public is much slower than the custom version, especially when the custom version is specially designed for specific types of objects. A class-specific distributor is an instance application of a fixed-size distributor, for example, a distributor provided in the Boost Pool library. If your application is single-threaded, but the default version of your compiler is thread-safe, you can achieve a considerable speed increase by implementing a thread-unsafe distributor. Of course, before deciding to increase the speed of operator new and operator delete, study your program to determine that these functions are actually bottlenecks.
  • Reduce the space overhead of default memory management. The general memory manager is not only slow, but also uses more memory. Because they introduce some additional overhead for each memory allocation block. The Allocator created for small objects fundamentally eliminates these overhead.
  • It can compensate for sub-optimal alignment in the default distributor. As I mentioned earlier, accessing double on a machine with X86 architecture is the fastest with 8-byte alignment. However, operator new in Some compilers cannot ensure that the dynamically allocated double is 8-byte aligned. In this case, replacing the default version with a version that can ensure 8-byte alignment can greatly improve the performance.
  • Aggregates related objects. If you know that some specific data structures are usually put together for use, you want to minimize the frequency of page errors when working on the data, creating a separate heap for these data structures makes sense, so that they can be clustered in as few pages as possible. Replace the default versions of new and delete to achieve this aggregation.
  • Unconventional behaviors can be obtained. Sometimes you want operator new and delete to do something that the compiler version cannot do. For example, you may want to allocate and release memory in the shared memory, but you only have one c api for memory management. Implementing the new and delete (maybe placement version -- See Item 52) of the custom version allows you to put on the C ++ coat for the c api. In another example, you can implement an operator delete to fill the released memory with zero data to enhance application data security.
5. Summary of these terms

There are many legitimate reasons for defining new and delete, including improving performance, debugging heap application errors, and collecting heap usage information.

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.