STL vectors and operator delete

Started by
18 comments, last by indigox3 18 years, 9 months ago
Hi Say I have the following:

class B
{

};

class A 
{
public:
std::vector< B > mBs;
};

class C
{
public:
	std::vector< A > mAs;
};

main()
{
	A aa;
	{
		B bb;
		aa.mBs.push_back( bb );
	}

	C* cc = new C;
	cc->mAs.push_back( aa );
	
	delete cc; // STL code is calling delete on elements of the aa's 
}

This pretty much does what you would expect. However, I have some real code similar to this, and delete is getting called (in the bowels of the STL code) on the B elements of A::mBs, when delete is called on cc. This causes a crash (probably because the elements of the vector are stack allocated objects) Why would delete be called on the elements of A::mBs?
Advertisement
The elements aren't stack allocated. The vector contains copies of the original values. Furthermore, while the elements' destructors get called when the vector is destroyed, delete isn't "called" on them.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I agree that the vector contains copies of the elements I am putting into it. However I'm not sure if the copies created on the stack or heap. (Probably heap thinking about it...)

Along those lines, ~vector() calls _Tidy() calls allocator::deallocate() calls delete with the pointer to the first element of the vector as an argument.

Must be something else going wrong then, I'll keep looking.

Thanks
Quote:Original post by indigox3
I agree that the vector contains copies of the elements I am putting into it. However I'm not sure if the copies created on the stack or heap. (Probably heap thinking about it...)

vector, and all dynamic containers (with the occasional exception of std::string in some implementations), only ever allocate on the heap.

Post your actual code, and we may be able to help.
From the sound of it you got a double delete bug comming from not the STL but missing copy and assignment operators in your own classes that probably have some sort of resource (like a pointer to dynamicly allocated memory).
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Quote:Original post by indigox3
I agree that the vector contains copies of the elements I am putting into it. However I'm not sure if the copies created on the stack or heap. (Probably heap thinking about it...)

Along those lines, ~vector() calls _Tidy() calls allocator::deallocate() calls delete with the pointer to the first element of the vector as an argument.

Must be something else going wrong then, I'll keep looking.



The allocator's allocate/deallocate methods deals solely with uninitialized memory. The default allocator (std::allocator) uses global operators new/delete via explicit invocation this gives/returns uninitialized memory, allocator's construst/destroy deal soley with de/initialization of uninitialized memory.

Typically (it is imp defined) std::vector is implementated with RAII techniques, std::vector may have a non-polymorphic base that deals with allocation and deallocation in the base destructor, then std::vector just destroys elements in its destructor after which the base deallocates memory.

Quote:Original post by Sneftel
... only ever allocate on the heap.


Never say never [grin], std::allocator uses heap but give them a custom allocator type that can use what ever you want [wink].
I can't post the actual code because of IP issues, but I did comment out pratically everything that could be giving me problems and the code boils down to:

class A : public B
{
public:
std::vector< int > mInts;
A(){};
~A(){};
};

main()
{
A* a = new A();

a->mInts.push_back(12);

...

HomeGrownVector v;
v.push( a );

...

for( int i = 0; i < v.size(); i++)
delete v; // dies here where A::mInts is destroyed.

}

I'm sure "a" isnt being deleted twice, bc I'm breaking on ~A() and its only getting called once.

The homegrown vector might be doing something weird, I'll have to check.
You must not delete elements you did not allocate using new. Since you never allocated the elements of v on the heap you must not delete them. just delete a, that will free all memory in your example.
Quote:Original post by snk_kid
The allocator's allocate/deallocate methods deals solely with uninitialized memory. The default allocator (std::allocator) uses global operators new/delete via explicit invocation this gives/returns uninitialized memory, allocator's construst/destroy deal soley with de/initialization of uninitialized memory.

Typically (it is imp defined) std::vector is implementated with RAII techniques, std::vector may have a non-polymorphic base that deals with allocation and deallocation in the base destructor, then std::vector just destroys elements in its destructor after which the base deallocates memory.


Wow - what a lot to say very little, still it probably felt intelligent at the time.

More simply, vectors allocate and deallocate memory as required.

If adding objects to a vector like in your example, the vector will allocate memory (on the heap using new) and make copies of your objects. Unless you're using a very old implementation of STL that contains such a bug, it's not a bug in STL. Certainly not one i've encountered anyway.
Quote:Original post by VolkerG
You must not delete elements you did not allocate using new. Since you never allocated the elements of v on the heap you must not delete them. just delete a, that will free all memory in your example.


Oops, I should have been more clear:
the v's are pointers, one of which, is the same as "a".

In other words v is a vector of pointers, not objects

This topic is closed to new replies.

Advertisement