Visual Studio 2010 C ++ Runtime Error

I met strange behavior in the Visual Studio 2010 C ++ compiler. After compiling the code, but it resets the "Debug error" after execution with the message:

"_ BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)"

It compiles and runs smoothly under GCC. It's my fault?

#include <iostream> #include <vector> using namespace std; typedef unsigned int uint; class Foo { vector<int*> coll; public: void add(int* item) { coll.push_back(item); } ~Foo() { for (uint i = 0; i < coll.size(); ++i) { delete coll[i]; coll[i] = NULL; } } }; int main() { Foo foo; foo.add(new int(4)); Foo bar = foo; return 0; } 
+4
source share
4 answers

You did not implement the copy constructor and copy assignment operator (see rule three). This results in a shallow copy of the pointers in your vector, which leads to double deletion and approval. EDIT: Double deletion is undefined behavior, so VS and gcc are correct here, they are allowed to do whatever they want.

Usually, when you implement a destructor with non-trivial behavior, you also need to write or disable copy building and copy assignment.

However, in your case, do you really need to store the elements by pointer? If not, just save them by value and this will fix the problem. Otherwise, if you need pointers, use shared_ptr (from your compiler or boost) instead of raw pointers to save you the trouble of writing your own destructor / copy methods.

EDIT: additional note about your interface: interfaces that transfer ownership of the ones passed in pointers can cause confusion on the part of people using your class. If someone passed an int address not allocated to the heap, then your destructor will fail anyway. It’s better to either accept the value if possible, or, if possible, clone your own new call to the add function in the add function.

+7
source

You delete the item twice because the line

 Foo bar = foo; 

Invokes the default copy constructor, which duplicates a pointer to an element, and does not select and copy data.

+3
source

The problem is that the element element bar and foo are the same. When foo goes out of scope, it calls a destructor, which frees the pointer, leaving the vector bar element hanging. bar destructor is trying to free its vector element, which remains dangling and causes you a runtime error. You must write a copy constructor.

 Foo bar = foo; // Invokes default copy constructor. 

Edit 1: Look at this topic to learn about Rule Three.

+2
source

A simpler solution here is to not use int* in the first place.

 #include <iostream> #include <vector> using namespace std; typedef unsigned int uint; class Foo { vector<int> coll; // remove * public: void add(int item) { // remove * coll.push_back(item); } // remove ~Foo }; int main() { Foo foo; foo.add(4); // remove `new` call Foo bar = foo; return 0; } 

In general, try to avoid new .

If you cannot, use an intelligent manager (e.g. std::unique_ptr ) to handle memory cleanup for you.

In any case, if you call delete manually , you are doing it wrong . Note: do not call delete and do not leak memory.

0
source

All Articles