C ++ Gotchas Terms 62: Replace Global New and Global Delete

zhaozj2021-02-08  467

Gotcha # 62: Replacing Global New and Delete

Gotcha Terms 62: Replace Global New and Global Delete

Replacing Operator New, Operator Delete, Array Delete's standard Global version is replaced with a custom version, which is almost not a good idea - even if C standards allow you to do this. The standard versions of these functions are generally optimized for the storage management of General-Purpose, and user-defined alternatives don't make a good meeting. (However, for a specific category or category system, the operation of the form (self-custom) member function is used to customize its memory management, it is usually reasonable.)

If the Operator New and Operator Delete make a behavior that is different from the standard version for a specific purpose, it may introduce a bug, as many standard libraries and the correctness of the third-party library rely on these functions default standards. Realize the version.

A more secure solution is to overload a function such as the global version of Operator New instead of replacing them. Suppose we want to populate the newly allocated storage with a specific character pattern:

Void * Operator new (size_t n, const string & pat) {

Char * p = static_cast (:: Operator new (n));

Const char * pattern = pat.c_str ();

IF (! Pattern ||! Pattern [0])

Pattern = "/ 0"; // Note: Two Null Chars

Const char * f = pattern;

For (int i = 0; i

IF (! * f)

f = pattern;

p [i] = * f ;

}

Return P;

}

The Operator New version receives a string pattern as a quotes and copies them into the newly allocated storage. Through overload analysis, the compiler can distinguish between standard Operator New and our own "version of the two quotes".

String Fill ("");

String * string1 = new string ("Hello"); // Standard version

String * string2 =

NEW (Fill) String ("World!"); // Reserved version

A heavy-duty Operator New version is also defined; in addition to Size_T as the first quota, the version also receives a VOID * type as the second quotes. This implementation is just simply returning second quotes. (Whose throw () syntax is an Exception-Specification, meaning that the function will not spread any exception. In the discussion and general case, it can be ignored.)

Void * Operator new (size_t, void * p) throw ()

{RETURN P;}

This is the standard Placement New for constructing an object in a specific location space. (It is different from that the standard "single amount operator new" can be replaced, and trying to replace the Placement New is illegal.) In essence, we will use it to "make the compiler mistake to call a constructor). The occasion of functions. For example, for an embedded application, we may want to construct a "Status Register" object on a particular hardware address: Class StatusRegister {

//.

}

Void * regaddr = reinterpret_cast (0xfe0000);

//.

// Place a register object in Regaddr

StatusRegister * SR = new (regaddr) statusregister;

Naturally, objects created via Placement New must be destroyed at some point. However, since the Placement New has not true allocated memory (the translation: it is only put into the object in the specified location, the memory allocation is not performed), so there is also no memory to be deleted when destroyed. Memolive, the behavior of the delete operator is: First arouse the "Want to delete the object" before calling the Operator Delete function (in order to return the storage space). For the case where the object is the 'spatial allocation' "by Placement New, in order to avoid any action to return to the memory space, we must explicitly call the destruction function when destroy the object (translation: this is The first step of delete operation, the second step "Call the Operator Delete function" does not have to do it).

SR-> ~ statusregister (); // Explicit call DTOR, do not call Operator Delete functions

Placement New and Explicit Destruction (Explicit Destructure Operation) are obviously very useful, but if they are not conservative and cautious, they are obviously very dangerous. (For details, please refer to the example of the Gotcha Terms 47 from the standard library.)

It should be noted that when we reload Operator Delete, these overload versions will never be evoked by "Express in the form of standard delete".

Void * Operator new (size_t n, buffer & buffer); // overload version of NEW

Void Operator Delete (void * p,

Buffer & buffer; // Corresponding overload version Delete

//.

Thing * Thing1 = New Thing; // Using the standard Operator New

Buffer buf;

Thing * Thing2 = new (buf) Thing; // Use the overload version of Operator New

DELETE Thing2; // Is wrong, you should use the overload version of Delete

Delete Thing1; / / correct, use standard Operator Delete

Correspondingly, for objects created via Placement New, we have to explicitly call the destructor's destructor, and then call the appropriate Operator delete function to explicitly go to the object's storage space. Equipped

Thing2-> ~ thing (); // correctly, destroy Thingoperator Delete (Thing2, BUF); // Correct, use the overload version of Delete

In practice, the storage space allocated via the "Operator New Web" is often erroneously erroneous via the "standard version of Global Operator New". A method to avoid this error is to ensure that any storage space allocated via "Global Operator New" is a storage space via the standard version of Global Operator New (Translation: Meaning, in "Global Operator In the implementation of the heavy load version of the New, you can get the space by calling the standard version of Global Operator New, see an example at the beginning of this Territic). This is the method used by the first overload implementation version (the translation: refers to the example of the example of this Territine. The standard version of the Global Operator Delete is normal:

String Fill ("");

String * string2 = new (fill) String ("world!");

//.

Delete string2; // Operation is normal!

In general, the overload version of Global Operator New either does not assign any storage space, or only the standard version of the WRAP GLOBAL OPERATOR NEW (Demolition: As shown in this Territor, the overload version Is a standard version of a Wrapper).

Usually, the best solution is to fully avoid the "Operator Functions" in Global Scope "to do handles, in order to customize the category or category with" Operator New, Operator Delete, Array "to customize the category or category. Memory management operation of the class system.

In the end of Gotcha Terms 61 We mentioned that if an exception is transmitted from the initialization operation in the New expression, the runtime system will evoke a "appropriate" Operator Delete function:

Thing * TP = New Thing (arg);

If the allocation of Thing is successful but the constructor throws an exception, the runtime system will evoke a suitable Operator delete function to return the unprogable memory pointed to by TP. In the above example, this "appropriate Operator Delete" is either the global version of Operator Delete (Void *) or is a member version of the same form. However, different Operator New means different Operator Delete:

Thing * TP = New (BUF) Thing (arg);

At this time, the appropriate Operator Delete should be "Double Core Version" Operator Delete (VOID *, BUFFER &), which corresponds to the "Operator New's overload version" used by the Thing assignment operation; this is the runtime system evoke version.

C gives a lot of flexibility in defining the behavior of memory management, with complexity as the price. Standard "Global Operator New" and "Global Operator Delete" are sufficient to meet most of the needs. Therefore, we should use more complex solutions only in the case of indeed need.

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

New Post(0)