[Disclaimer: All Rights Reserved. You are welcome to reprint it. Do not use it for commercial purposes. Contact Email: feixiaoxing @ 163.com]
Pointers are a nightmare for programmers. They are also true for C developers and C ++ developers. Especially in C ++, if you do not pay attention to the pointer in the processing class, it is very prone to problems. If you do not believe it, you can look at the following code:
Class data
{
Int * value;
Public:
Data (int num ){
If (num> 0)
Value = (int *) malloc (sizeof (int) * num );
}
~ Data (){
If (value)
Free (value );
}
};
Void process ()
{
Data m (10 );
Data p = m;
}
Class data
{
Int * value;
Public:
Data (int num ){
If (num> 0)
Value = (int *) malloc (sizeof (int) * num );
}
~ Data (){
If (value)
Free (value );
}
};
Void process ()
{
Data m (10 );
Data p = m;
} Is there any problem with the above question? You can draw a sketch on the draft paper by yourself. Then verify it in the actual environment. Sure, the system prompts a memory error. Why? This is because the memory is released twice. Let's take a look at the assembly code of process:
21: data m (10 );
0040105D push 0Ah
0040105F lea ecx, [ebp-10h]
00401062 call @ ILT + 15 (data: data) (00401014)
00401067 mov dword ptr [ebp-4], 0
22: data p = m;
0040da-e mov eax, dword ptr [ebp-10h]
00401071 mov dword ptr [ebp-14h], eax
23 :}
00401074 lea ecx, [ebp-14h]
00401077 call @ ILT + 5 (data ::~ Data) (0040100a)
00401_c mov dword ptr [ebp-4], 0 FFFFFFFFh
00401083 lea ecx, [ebp-10h]
00401086 call @ ILT + 5 (data ::~ Data) (0040100a)
00401_ B mov ecx, dword ptr [ebp-0Ch]
004020.e mov dword ptr fs: [0], ecx
00401095 pop edi
00401096 pop esi
00401097 pop ebx
00401098 add esp, 54 h
004010000b cmp ebp, esp
004010000d call _ chkesp (004015b0)
004010A2 mov esp, ebp
004010A4 pop ebp
004010A5 ret
21: data m (10 );
0040105D push 0Ah
0040105F lea ecx, [ebp-10h]
00401062 call @ ILT + 15 (data: data) (00401014)
00401067 mov dword ptr [ebp-4], 0
22: data p = m;
0040da-e mov eax, dword ptr [ebp-10h]
00401071 mov dword ptr [ebp-14h], eax
23 :}
00401074 lea ecx, [ebp-14h]
00401077 call @ ILT + 5 (data ::~ Data) (0040100a)
00401_c mov dword ptr [ebp-4], 0 FFFFFFFFh
00401083 lea ecx, [ebp-10h]
00401086 call @ ILT + 5 (data ::~ Data) (0040100a)
00401_ B mov ecx, dword ptr [ebp-0Ch]
004020.e mov dword ptr fs: [0], ecx
00401095 pop edi
00401096 pop esi
00401097 pop ebx
00401098 add esp, 54 h
004010000b cmp ebp, esp
004010000d call _ chkesp (004015b0)
004010A2 mov esp, ebp
004010A4 pop ebp
004010A5 ret
Row 21: data calls the constructor and allocates memory to the value.
Row 22: here we find that the program is copying memory, so the value of m variable value is the same as the value of p variable.
Row 23: The function is about to end, so the system calls the destructor of m and p. The memory pointed to by value is released at the first destructor, in the second structure, because the value of the p variable is not 0, the memory needs to be released. Of course, the structure is also required, but the memory has been released at this time, therefore, the system reports an error when the memory is released twice.
After the above research, we found the problems and causes. How should we solve them? Since the problem lies in the copy function, it is necessary to perform special processing on the copy function. I personally understand that there are two ways to choose from:
(1) perform private processing on the copy constructor. Once a copy operation occurs, the compiler prompts an error.
Class data
{
Int * value;
Data (const data &);
Public:
Data (int num ){
If (num> 0)
Value = (int *) malloc (sizeof (int) * num );
}
~ Data (){
If (value)
Free (value );
}
};
Class data
{
Int * value;
Data (const data &);
Public:
Data (int num ){
If (num> 0)
Value = (int *) malloc (sizeof (int) * num );
}
~ Data (){
If (value)
Free (value );
}
}; (2) Write a copy constructor for deep memory Replication
Class data
{
Int * value;
Int number;
Public:
Data (int num ){
If (num> 0)
Value = (int *) malloc (sizeof (int) * num );
Number = num;
}
Data (const data & d ){
If (NULL! = D. get_ptr ())
Value = (int *) malloc (sizeof (int) * d. get_number ());
Number = d. get_number ();
Memmove (value, d. get_ptr (), sizeof (int) * number );
}
~ Data (){
If (value)
Free (value );
}
Int * get_ptr () const {return value ;}
Int get_number () const {return number ;}
};
Class data
{
Int * value;
Int number;
Public:
Data (int num ){
If (num> 0)
Value = (int *) malloc (sizeof (int) * num );
Number = num;
}
Data (const data & d ){
If (NULL! = D. get_ptr ())
Value = (int *) malloc (sizeof (int) * d. get_number ());
Number = d. get_number ();
Memmove (value, d. get_ptr (), sizeof (int) * number );
}
~ Data (){
If (value)
Free (value );
}
Int * get_ptr () const {return value ;}
Int get_number () const {return number ;}
}; We can see that after copying the definition of the constructor, the original process function solution can be compiled normally, no problem