Standard C ++ String Copy-On-Write Technology (3)

zhaozj2021-02-16  51

2.3.4, what is the specific implementation of Copy-on-Write?

In the final problem, we mainly solve the problem of the "democratic concentration". Please look at the following code first:

String h1 = "hello";

String H2 = H1;

String H3;

H3 = H2;

String w1 = "world";

String w2 ("" ");

W2 = W1;

Obviously, we have to share the same memory with H1, H2, and H3, let W1, W2 share the same memory. Because, in H1, H2, H3, we have to maintain a reference count, in W1, W2 we have to maintain a reference count.

How to use a clever way to generate these two reference counts? We think that the String class's memory is dynamically allocated on the pile. Since all classes of shared memory points to the same memory area, why not allocate a single space in this area to store this reference count? In this way, all classes that share a memory area have the same reference count, and the address of this variable is on the shared area, then all classes that share this memory can be accessed, and they know this block. How much is stored in memory.

Please see the picture below:

So, there is such a mechanism, whenever we allocate memory for String, we always have to allocate a space to store the value of this reference count. As long as the copy construct can be assigned, the value of this memory will add one. . When the content is modified, the String class is to view this reference count is 0. If it is not zero, it means that someone is sharing this memory, then you need to make a copy, then reduce the reference count, then put data Copy. The following sequences describe these two actions:

// Constructor (Sub-memory)

String :: string (const char * tmp)

{

_Len = Strlen (TMP);

_Ptr = new char [_len 1 1];

STRCPY (_PTR, TMP);

_PTR [_LEN 1] = 0; // Settings a reference count

}

// Copy construct (shared memory)

String :: string (const string& str)

{

IF (* this! = Str) {

this -> _ ptr = str.c_str (); // Share memory

THIS -> _ len = str.szie ();

this -> _ ptr [_len 1] ; // Reference count plus one

}

}

// Copy Copy-on-Write when writing

Char & string :: Operator [] (unsigned int idx)

{

IF (idx> _len || _ptr == 0) {

Static char nullchar = 0;

Return nullchar;

}

_PTR [_LEN 1] -; // Reference counting minus one

Char * TMP = New Char [_LEN 1 1];

STRNCPY (TMP, _PTR, _LEN 1);

_PTR = TMP;

_PTR [_len 1] = 0; // Set a reference count for new shared memory

Return_PTR [IDX];

}

// Some of the processing functions ~ String () {

_PTR [_LEN 1] -; // Reference counting minus one

// When the reference count is 0, the memory IF is released (_ptr [_len 1] == 0) {delete [] _ptr;}} Haha, the entire technical details completely surface.

However, this and the implementation details of Basic_String in STL have a little difference. When you open the STL source code, you will find that the counting count is through such access: _ptr [-1], standard library, put this reference The counting memory is allocated in front (I give the code to allocate the reference count, this is very bad), the benefits of allocating in front of the String, only need to extend its memory after String, and There is no need to move the memory storage location of the reference count, which saves a little time.

The STRING memory structure in STL is like the figure I have drawn in front, _PTR pointed to the data area, and REFCNT is in _ptr-1 or _PTR [-1].

2.4, bug bug

Who said "There will be darkness in the place where the sun is"? Perhaps many of us are very superstitious about standard things, think it is a long-term test, it is impossible to mistake. Oh, don't have this kind of superstition, because any design is good, the code is good, the code will have bugs in a particular situation, STL is the same, the String class shared memory / write time copy technology is not Exception, and this bug may also let your entire program Crash!

Do not believe? ! So let's take a test case:

Suppose there is a dynamic link library (called MyNet.dll or MyNet.so), there is such a function to return String class:

String getipaddress (String hostname)

{

Static string IP;

......

......

Return IP;

}

And dynamically load this dynamic link library in your main program and call this function:

Main ()

{

/ / Load function in dynamic link library

HDLL = loadingLibraray (... ..);

PFUN = GetModule (HDLL, "Getipaddress");

// Call the function in the dynamic link library

String IP = (* pfun) ("Host1");

......

......

// Release Dynamic Link Library

Freelibrary (HDLL);

......

Cout << ip << endl;

}

Let's take a look at this code, the program loads the function in the dynamic link library in dynamic mode, then call the function in the dynamic link library in a function pointer, and put the return value in a string class, then release it. This dynamic link library. After release, enter the contents of IP.

Depending on the definition of the function, we know that the function is "value returns", so when the function returns, the copy constructor will be called, and according to the String class's memory sharing mechanism, the variable IP in the main program is the statics inside the function. String variable shared memory (this memory area is the address space of the dynamic link library). And we assume that there is no modification of the value of IP throughout the main program. Then after the main program releases the dynamic link library, the shared memory area is also released. Therefore, the access to IP will inevitably make memory address access illegal, resulting in program CRASH. Even if you don't use IP variables in the future, memory access exception occurs when you exit, because the program exits, the IP session, the memory access exception occurs during the destructor.

Memory access is abnormal, meaning two things: 1) No matter your program is beautiful, you will have a dim light, your reputation will be lost because of this error. 2) For a while, you will suffer from this system-level error (in the C world, find and exclude such memory error is not an easy task). This is the pain of C / C programmers forever, and the embankment of a thousand miles is collapsed in the ant hole. And if you don't know this feature of the String class, find such a memory abnormality in thousands of lines of lines, it is simply a nightmare. Remarks: To correct the above BUG, ​​there are many ways, here there is provided for reference only:

String ip = (* pfun) ("Host1"). cstr ();

3, post

The article should also be over here. This article has the following purposes:

1) Let you introduce you to copy / memory sharing this technology.

2) Take the String class in STL as an example, introduce a design pattern to you.

3) In the C world, regardless of your design, how is the code is stable, it is difficult to take care of all the situation. Intelligent pointers are a typical example, no matter how you design, there will be very serious bugs.

4) C is a double-edged sword, only understand the principle, you can use C . Otherwise, it will sure it. If you have a feeling of "playing C like playing fire when designing and using the class library, you must get started, wait for you to control the" fire "control, that is Learned.

Finally, use this in this back, introduce yourself. I have currently engaged in software development under all UNIX platforms, mainly to develop system-level product software research and development, and is very interested in the next-generation computer revolution - grid computing, with distributed computing, P2P, Web Service, The J2EE technical direction is also very interested, in addition, for project implementation, team management, project management is also small, hoping to fight with me in the "technology and management and serious", can communicate with me. My MSN and emails are: haoel@hotmail.com.

My column is:

http://blog.9cbs.net/haoel/

<- Previous Page

(All rights reserved, please indicate the author and the source when reproduced)

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

New Post(0)