代码改变世界

Deleted pointer causes undefined behaviour

2014-08-10 14:45  大脑溢出  阅读(209)  评论(0编辑  收藏  举报

这文章是早期闲得用英文写的,删除了怪可惜的,贴出来证明自己会英文算了。。。

Occasionally,on stackoverflow.com,I found a classic problem which is age-old but never to be out-dated,that is,the undefined behaviour occurred by reusing the pointer which was just deleted.
The code below may be a good example.(This piece of code refers to here)


 1  #include <iostream>
 2     class MyClass
 3     {
 4     public:  
 5         int a;
 6         MyClass() : a(10) 
 7         {        
 8              std::cout << "constructor rann";  
 9         }
10         void method(std::string input_) 
11         {   
12             std::cout << input_.c_str()<< "n";
13         }
14         ~MyClass() 
15         {       
16             std::cout << "destructor rann";  
17         }
18     };
19     int main()
20     {
21          MyClass* ptr = new MyClass;
22          ptr->method("1");
23          delete ptr;
24          ptr->method("2.5");
25     }
26  

I used CL.exe(Version 17.00) and g++(Version 4.6) to run this code.

This code outputs:
constructor ran
1
destructor ran
2.5

Actually,I also confronted a confusing problem like this one when I was a c++ beginner(Until now,I’m still green at c++).I fear that I couldn’t believe what happened if I didn’t test what the value of variable a was.
So I added

 cout<<a<<endl

to line 27 and this code outputs:

Constructor ran
1
destructor ran
2.5
-17891602

At that time, I realized that the memory allocated to ptr was actually deleted.
Well...now,let us look at the definition of delete from Wiki:

"The delete operator calls the destructor of the given argument, and returns memory allocated by new back to the heap.",and the description of deallocation from N3376:

"If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value, the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value is undefined."

As for our program,after deleting the storage referenced by ptr, the manipulation on ptr is undefined.Under our current condition,ptr points to the same data it pointed to before and calling methods on it just works “fine”, but it’s not what we want and what we expect because maybe at next second,the allocator will allocate this memory to someone else.So,there is a recommended common method to deal with this counterintuitive problem:

 delete ptr;
 ptr = NULL;  

In this way,you could ensure that you won’t incautiously reuse this pointer before a piece of new memory is reallocate-d to it.
In conclusion,I suggest that you shouldn’t rely on pointer type unless it’s necessary.In most cases,reference is enough for us to solve problems.