C ++ Memory Management

Source: Internet
Author: User

1. The corresponding new and delete statements must adopt the same form. What are the errors in the following statements?
String * stringarray = new string [100];
...
Delete stringarray;

Everything seems to be in order-a new corresponds to a delete-but there is a big mistake hidden: The running status of the program will not be guessed. At least 99 of the 100 string objects pointed to by stringarray will not be correctly destroyed, because their destructor will never be called.

Two things will happen when new is used. First, the memory is allocated (by using the Operator new function, see terms 7-10 and m8), and then one or more constructors are called for the allocated memory. When using delete, there are also two things: first, call one or more destructor for the memory to be released, and then release the memory (through the operator delete function, for details, see clause 8 and m8 ). For delete, there is an important question: how many objects in the memory will be deleted? The answer determines how many destructor will be called.

Simply put, the pointer to be deleted points to a single object or an object array? Only you can tell delete. If you use delete without parentheses, delete will point to a single object. Otherwise, it will point to an array:

String * stringptr1 = new string;
String * stringptr2 = new string [100];
...

Delete stringptr1; // delete an object
Delete [] stringptr2; // delete an array of Objects

What if you add "[]" before stringptr1? The answer is: it would be unpredictable. What if you didn't add "[]" before stringptr2? The answer is no guess. In addition, for a fixed type such as int, the results cannot be guessed, even if such a type does not have a destructor. Therefore, the rule for solving such problems is simple: if [] is used when you call new, [] is also used when you call delete. If [] is not used when new is called, [] is not used when delete is called.

This rule is especially important when writing a class that contains pointer data members and provides multiple constructors. In this case, you must use the same new form in all constructors that initialize pointer members. Otherwise, what form of delete will be used in the Destructor? For more information about this topic, see clause 11.

This rule is also important for people who like to use typedef, because programmers who write typedef must tell others that after creating a typedef-Defined Object with new, the form of delete to delete. Example:

Typedef string addresslines [4]; // a person's address. There are 4 rows in total, each line has a string
// Because addresslines is an array, use new:
String * pal = new addresslines; // pay attention to "new addresslines" to return string *, and
// "New string [4]" returns the same
Delete must correspond to it in array format:
Delete pal; // error!
Delete [] pal; // correct

To avoid confusion, we recommend that you do not use typedefs for array types. This is actually very easy, because the standard c ++ Library (see cla49) contains stirng and vector templates, using them will reduce the need for arrays to almost zero. For example, addresslines can be defined as a string vector, that is, addresslines can be defined as a vector.

2. Call delete For pointer members in the destructor

In most cases, classes that execute dynamic memory allocation use new to allocate memory in the constructor, and then delete to release memory in the destructor. It is certainly not difficult to write this class at the beginning. You will remember to use delete for all the members allocated with memory in all constructors.

However, after the class is maintained and upgraded, the situation becomes difficult, because the programmer who modifies the class code is not necessarily the first person to write the class. Adding a pointer member means almost all of the following work is required:
· Initialize the pointer in each constructor. For some constructors, if there is no memory to allocate to the pointer, the pointer should be initialized to 0 (that is, a null pointer ).
· Delete the existing memory and assign it to the new memory of the pointer through the value assignment operator.
· Delete the pointer in the destructor.

If you forget to initialize a pointer in the constructor or forget to process it during the value assignment operation, the problem will appear very fast and obvious, in practice, these two problems will not affect you. However, if the pointer is not deleted in the destructor, it does not show obvious external symptoms. On the contrary, it may only show a small amount of memory leakage, and continues to grow. In the end, it swallowed up your address space, leading to program failure. This situation is often less appealing, so every time you add a pointer member to a class, you must note it clearly.

In addition, deleting a null pointer is safe (because it does not do anything ). Therefore, when writing constructors, value assignment operators, or other member functions, each pointer member of the class either points to a valid memory or points to null, in your destructor, you can simply delete them without worrying about whether they have been replaced by new ones.

Of course, do not use these terms absolutely. For example, you certainly won't use delete to delete a pointer that does not use new for initialization, and you don't have to delete it when using smart pointer objects, you will never delete a pointer that is passed to you. In other words, unless the class members use new, they do not need to use delete in the destructor.

Speaking of smart pointers, this article introduces a method to avoid having to delete pointer members, that is, replacing these Members with smart pointer objects, such as auto_ptr in the c ++ standard library. If you want to know how it works, check the terms m9 and m10.

3. Prepare insufficient memory in advance
Operator new throws an exception when the memory allocation request cannot be completed (in the past, 0 is generally returned, and some earlier compilers still do this. You can set your compiler to this way if you like. I will postpone the discussion to the end of these terms ). As we all know, dealing with exceptions caused by insufficient memory can be regarded as a moral behavior, but it will be as painful as the rest of the neck. So sometimes you don't care about it, maybe you never care about it. But you must have a deep sense of guilt hidden in your mind: What should you do if new really has an exception?
You will naturally think of a way to deal with this situation, that is, back to the Old Road and use preprocessing. For example, a common practice of c is to define a type-independent macro to allocate memory and check whether the allocation is successful. For c ++, this macro may look like this:


# Define new (ptr, type)
Try {(ptr) = new type ;}
Catch (std: bad_alloc &) {assert (0 );}

("Slow! Std: What does bad_alloc do ?" You will ask. Bad_alloc is the exception type thrown when operator new cannot meet the memory allocation request. std is the name of the namespace where bad_alloc is located (see article 28. "Good !" You will continue to ask, "What is the use of assert ?" If you look at the Standard c header file (or use the namespace version for the same price as it, see clause 49), you will find that assert is a macro. This macro checks whether the expression passed to it is non-zero. If it is not a non-zero value, an error message is sent and abort is called. Assert does this only when the standard macro ndebug is not defined. In the product release status, when ndebug is defined, assert does nothing, which is equivalent to an empty statement. Therefore, you can only check assertion during debugging )).

The new macro not only has the common problem mentioned above, that is, it uses assert to check the status that may occur in a published Program (however, there may be insufficient memory at any time). At the same time, it also has another defect in c ++: it does not take into account the various usage methods of new. For example, to create a type t object, there are generally three common syntax forms. You must handle all possible exceptions in each form:


New t;
New t (constrUCtor arguments );
New t [size];

The problem is greatly simplified here, because someone will also customize (reload) operator new, so the program will contain any new syntax format.

So what should we do? If you want to use a very simple error processing method, you can do this: when the memory allocation request cannot meet, call an error processing function you specified in advance. This method is based on a general rule, that is, when operator new cannot meet the request, it will call an error processing function specified by the customer before throwing an exception -- generally called the new-handler function. (Operator new must be more complex in actual work. For details, see section 8)

The set_new_handler function is used to specify the error handling function. It is defined as follows in the header file:


Typedef void (* new_handler )();
New_handler set_new_handler (new_handler p) throw ();

New_handler is a custom function pointer type that points to a function without input parameters or return values. Set_new_handler is a function of the new_handler type input and returned.

The input parameter of set_new_handler is the pointer to the error processing function to be called when operator new fails to allocate memory. The returned value is the pointer to the old error processing function that has been in effect before set_new_handler is called.

You can use set_new_handler as follows:


// Function to call if operator new cant allocate enough memory
Void nomorememory ()
{
Cerr <"unable to satisfy request for memory
";
Abort ();
}

Int main ()
{
Set_new_handler (nomorememory );
Int * pbigdataarray = new int [100000000];

...

}

If operator new cannot allocate space for 100,000,000 integers, nomorememory will be called and the program will terminate after an error message is sent. This is better than simply making the system kernel generate an error message to end the program. (By the way, if cerr needs to dynamically allocate memory when writing error messages, what will happen ...)

When operator new cannot meet the memory allocation request, the new-handler function is called not only once, but repeats until enough memory is found. The code for implementing repeated calls can be seen in Clause 8. Here I use descriptive language to explain: a well-designed new-handler function must implement one of the following functions.
· Generate more available memory. This may make operator new's next attempt to allocate memory possible. One way to implement this policy is to allocate a large memory block when the program starts and release it when new-handler is called for the first time. The release is accompanied by some user warning information, such as a small amount of memory, the next request may fail unless there is more available space.
· Install another new-handler function. If the current new-handler function cannot generate more available memory, it may know that another new-handler function can provide more resources. In this case, the current new-handler can install another new-handler to replace it (by calling set_new_handler ). When operator new calls new-handler

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.