First, preface
Suppose we have a car class, used to represent a vehicle, it has many things like ID, name, license plate, and a carpart that represents the car's parts.
But for some reason, we are not going to produce this car when the object of car is produced, you can think that this time, only a paper-pasted car in front of you, it has ID, there is a name, there is a license, but it can not move, only we intend to start the car when the car to configure the engine, Tires and other components.
Second, error code 1
The Carpart class used to identify the individual parts of the vehicle.
Car class with a logo vehicle
We define a car class with a _id that identifies the car and a _car to identify the individual parts of the vehicle, and at the very beginning, the _car pointer is null, and when we call Getcar, we determine if the car is creating a part, and some return the part, If not, create parts for this car, as for the specific steps of creation, perhaps in a factory, perhaps from somewhere else, and then back to the parts of the car.
Main function
We create car objects in a loop, create the car's parts, and put this object into a vector, in which we only loop once, as for the reason you see below
Then we run the program and it just starts to look normal, but bad ... There was a problem with the program
g++-G Main.cpp-o main.out//(Use the-G option to generate debug files)
./main.out
Start
Make 4 tires of car 0
Make engine of car 0
-------------------
End
GLIBC detected * * * double free or corruption (fasttop): 0x0000000000503010 * * *
We saw some problems with the program, and a core file was created
Let's take a look at this core file with GDB.
GDB Main.out
(GDB) Core-file core.45393
(GDB) bt
#0 0x0000003f0b02e2ed in Raise () from/lib64/tls/libc.so.6
#1 0x0000003f0b02fa3e in Abort () from/lib64/tls/libc.so.6
#2 0x0000003f0b062d41 in __libc_message () from/lib64/tls/libc.so.6
#3 0x0000003f0b06881e in _int_free () from/lib64/tls/libc.so.6
#4 0x0000003f0b068b66 in free () from/lib64/tls/libc.so.6
#5 0x000000342cfae19e in operator delete () from/usr/lib64/libstdc++.so.6
#6 0x0000000000400dc0 in ~car (this=0x503030) at car.h:29
#7 0x00000000004016fd in std::_destroy<car> (__pointer=0x503030) at/usr/lib/gcc/x86_64-redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_construct.h:107
#8 0x000000000040155b in Std::__destroy_aux<car*> (__first=0x503030, __last=0x503040) at/usr/lib/gcc/x86_64- redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_construct.h:120
#9 0x0000000000401103 in Std::_destroy<car*> (__first=0x503030, __last=0x503040) at/usr/lib/gcc/x86_64- redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_construct.h:152
#10 0x0000000000400f89 in ~vector (this=0x7fff0f7371a0) at/usr/lib/gcc/x86_64-redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_vector.h:256
#11 0x0000000000400d0a in Main () at main.cpp:17
We see that the program ends at line 17th of the program, and the problem that occurs when the destructor is called
The cause of an error in a destructor is usually to release the same piece of memory multiple times
So where does the problem arise?
Let's think about line 12th we created a temp object and then the 13th behavior the Temp object created the Auto component
This time the memory looks like this
Then we put temp in the vector, this time call car copy constructor, because car does not define its own copy constructor, so will execute the default copy constructor for shallow copy operation
This time the memory is like this
When the first loop is finished, temp is refactored and the auto component is deleted.
Then when the program ends, the vcar[0] is destroyed, because the _car object in temp _car and vcar[0] points to the same piece of content, vcar[0] refers to the car component has been released, again delete, causing errors
Third, error code 2
We've just looked at a version of the error code, now let's look at another version of the error code
Carpart and car classes are the same as in the previous version
Main function is different
Instead of working directly with the Temp object, we get the object just push_back through Vcar.back () and getcar on it, thus avoiding the pointer in temp and vcar[0] pointing to the same piece of memory
We run the program and everything looks normal.
Start
Make 4 tires of car 0
Make engine of car 0
-------------------
End
Then we'll make the 10th line a little bit of a change, let it loop 2 times, run again, damn it, the program went wrong.
Start
Make 4 tires of car 0
Make engine of car 0
-------------------
Make 4 tires of car 1
Make engine of car 1
-------------------
End
GLIBC detected * * * double free or corruption (fasttop): 0x0000000000503030 * * *
View the core file and discover that there is a problem at the destructor
(GDB) bt
#0 0x0000003f0b02e2ed in Raise () from/lib64/tls/libc.so.6
#1 0x0000003f0b02fa3e in Abort () from/lib64/tls/libc.so.6
#2 0x0000003f0b062d41 in __libc_message () from/lib64/tls/libc.so.6
#3 0x0000003f0b06881e in _int_free () from/lib64/tls/libc.so.6
#4 0x0000003f0b068b66 in free () from/lib64/tls/libc.so.6
#5 0x000000342cfae19e in operator delete () from/usr/lib64/libstdc++.so.6
#6 0x0000000000400f80 in ~car (this=0x504080) at car.h:42
#7 0x0000000000401b65 in std::_destroy<car> (__pointer=0x504080) at/usr/lib/gcc/x86_64-redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_construct.h:107
#8 0x00000000004019d5 in Std::__destroy_aux<car*> (__first=0x504080, __last=0x5040a0) at/usr/lib/gcc/x86_64- redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_construct.h:120
#9 0x0000000000401411 in Std::_destroy<car*> (__first=0x504060, __last=0x5040a0) at/usr/lib/gcc/x86_64- redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_construct.h:152
#10 0x0000000000401259 in ~vector (this=0x7fff3ead6110) at/usr/lib/gcc/x86_64-redhat-linux/3.4.5/. /.. /.. /.. /include/c++/3.4.5/bits/stl_vector.h:256
#11 0x0000000000400ea2 in Main () at main.cpp:18
(GDB)
Why do you make a mistake by changing the cycle from one to two times?
We're going in. If you print the address of _car in Vcar, you'll find that they're the same.
So why is that?
In C + +, heap memory is possible for reuse, and if the previous memory has been released, the memory of the new object may be built on the memory that was just freed when the new object
We know that inside the vector is a contiguous array-like storage space.
When the vector is found to be out of space, it re-applies a memory space elsewhere, calls the copy constructor of the original object to create it in a new place, and the original place object is
The first time the vector size is 1, the capacity is 1, in the second call, because of this time, put in the second element, so the size of the vector needs to be adjusted, then in the new place to apply for a piece of memory, called the car's copy constructor, and the original object to the destruction, So the _car address of the object created for the second time is the same as the first object
So when the program ends calling the destructor, the problem occurs when the delete occurs because _car points to the same memory in vcar[0] and vcar[1]
The root of the problem is still no deep copy constructor
Iv. Conclusion
1, assignment function, copy constructor, destructor is usually considered as a whole, that is, the class that needs the destructor also needs assignment function and copy constructor, and vice versa
2. In order to support fast access, vectors store elements continuously, and when they have to acquire new memory space, the vector will apply for new space elsewhere and move elements from the old place to the new place, during which the element's destructor and copy constructor are called
3, C + + heap memory can be reused, when you release a piece of memory, and immediately request a piece of memory, the new application of memory space is likely to be in the memory just released
A lot of knowledge introduced by a C++bug