C ++ Gotchas Terms 61: Check the situation of memory allocation failure

zhaozj2021-02-08  383

Gotcha # 61: Checking for Allocation Failure

Gotcha Terms 61: Checking the Failure of Memory Allocation

Some questions should not ask, "whether a memory allocation action is successful" is a one.

Let's take a look at what memory allocation in C has been like. The following code carefully checks the success of each memory allocation:

BOOL Error = false;

String ** array = new string * [n];

IF (array) {

FOR (String ** P = Array; P

String * TMP = New string;

IF (TMP)

* p = TMP;

Else {

Error = True;

Break;

}

}

}

Else

Error = True;

IF (Error)

HandleError ();

This coding style will bring a lot of trouble. If there is this possible memory allocation failure, then it is worth doing. Non-also. Unfortunately, String Constructor itself may encounter memory allocation errors, and there is no good way to pass this error out of constructor. One possible (but the foreground is not optimistic) method is that (when an error) allows String Constructor to make String Object in an acceptable error state, and set a FLAG to be detected by the user of this category. Even if we can contact String's implementation code to achieve this behavior, this method is still a status that requires testing for the original author of the code and all maintaists.

Or we can ignore the test. As described above, the error check code is hardly written correctly at the beginning, and it is almost impossible to be correct after a period of maintenance. Better solution is that you will not check it all:

String ** array = new string * [n];

FOR (String ** P = array; p

* p = new string;

This code is shorter, clearer, faster, and it is correct. NEW's standard behavior is that a Bad_alloc Exception is thrown when the allocation failure event occurs. This allows us to encapsulate the error handling code required when the assignment fails, so that it is separated from the remaining procedures to form a cleaner, clearer, generally more efficient design.

Since the use of New, it is necessary to throw an exception, so it is impossible to measure the results of how to try the results of the NEW standard usage:

INT * ip = new int;

IF (ip) {// Conditions always true for TRUE

//.

}

Else {

// Never do it here

}

But we can use the "Nothrow" version of the Operator New standard, which will return a null Pointer when failed:

INT * IP = New (nothrow) int;

IF (ip) {// Condition is almost always true

//.

}

Else {

// I have almost don't do it here.

}

However, this is also re-brought back to the problem involved in the old old semantism involved in the old semantic language, and the harm caused by the ugly syntax. It is best to avoid using this clumsy backward compatible method, and directly use new NEW to design and encode.

The runtime system also automatically processes a particularly harsh issue when allocating fails. Recalling the previously mentioned, New Operator actually established two function calls: a call to the Operator New function to allocate storage; then the conformation function is used to initialize the assigned space: Thing * TP = New Thing (arg);

If we caught a Bad_alloc Exception, we know that there is a memory allocation error, but where is wrong? Error may occur in the original allocation of the storage space for this, may also occur in the constructor of the Thing. In the first case, we didn't need to match the memory because TP has not been set to anything. In the second case, we should return the (not yet initialized) memory pointed to HEAP. However, we must determine which one is very difficult or even impossible.

Fortunately, the runtime system will handle this situation. If the original allocation of the storage space is successful, the Thing Constructor fails and throws any exception, then the runtime system calls the appropriate Operator Delete (see Gotcha Terms 62) to return (allocated but not initialized) storage.

转载请注明原文地址:https://www.9cbs.com/read-398.html

New Post(0)