   Damn mem leaks - std::vector, where is it?
  Dude, its unbelievable, Im getting nuts, I tried to isolate piece by piece, with made me think I found the problem, but its kind crazy, Im not understanding...Lets say I have a struct A and a struct B ok?struct A have a vector of structs B, like thisstruct A{std::vector vBs;}And I have a vector of structs A:std::vector[A] vAs;So I have a loop that read a file and depending of that file it can add A elements to the vAs. So what I have is a single A tmp object that I call actual_A, that I use just to fill it with file data(actual_A.vBs.push_back(actual_B) ) and at the end of the loop I add this to the vAs, like this:vAs.push_back(actual_A);So obviously, just after that line I clean the damn actual_A`s B vector, like this:actual_A.vBs.clear();A destruct is responsible for cleaning vAs, like this:for( UINT i=0; i<vAs.size(); i++ )vAs.vBs.clear();vAs.clear();Am I missing any cleaning?What I did to try to figure out is commenting out things until no mem leaks happen, with I figure out the problem really is with actual_A, because commenting every "actual_A.VBs.push_back(actual_B)" solve the mem leaks.But its nonsense to me that, if, letting the "actual_A.VBs.push_back(actual_B)"(not commenting it out), but adding actual_A.VBs.clear() just on the next line still produce mem leaks!! How can that be? Doesnt that makes actual_A empty, and than I just have to clean vAs like my destruct is doing?..I debuged it step by step, everything looks fine..heres the entire scope of the code, still generic:do{ File.getline switch( line stuff ){  case a: ... break;//other stuff(doesnt use actual_A or vAs)  case b://read this block line by line    //since can get here more than once, clean actual_A stuff    //here actual_A.vBs is suppose to be empty since it is cleared    //at the end of this case label    ZeroMemory(&actual_A, sizeof(actual_A)); do{   File.getline    switch( line stuff )case x:  actual_B = stuff;  actual_A.vBs.push_back(actual_B);//commenting this solve mem leak  //actual_A.vBs.clear();//this DOESNT solve!how can that be?break;case y:  actual_B = stuff;  actual_A.vBs.push_back(actual_B);//commenting this solve mem leak  //actual_A.vBs.clear();//this DOESNT solve!how can that be?break;   }while( line stuff != b )//until next b   vAs.push_back(actual_A);   actual_A.vBs.clear();   break;//case b end }}while( !eof )Now the probaly key information to solve this are those:The leak just happens if the "case b" label is achieved more than once;The size of the leaks depends on how much stuff the "b" label on the file have,and the count of the leaks depends on how much "b"s the file have, BUTadding the "actual_A.vBs.clear();" lines reduces the leaks size by a fix size(but the count is still the same...Of course my point is not clear actual_A.vBs just after updating it, Im just trying to figure out wheres the leak..struct B have no vector or heap mem stuff.Thats so annoying.
Quote://since can get here more than once, clean actual_A stuff//here actual_A.vBs is suppose to be empty since it is cleared//at the end of this case labelZeroMemory(&actual_A, sizeof(actual_A));No!Do this instead:// Assign an empty "A" to "actual_A"actual_A = A();   ;Quote:Thats so annoying.I don't know that there's anything annoying going on here. (Rather, it just looks like you may be a bit confused about how std::vector works.)How are you determining that a memory leak has occurred? Also, could you post a complete, compilable program that demonstrates the behavior?As _fastcall mentioned, you don't want to be using ZeroMemory() with non-POD types such as std::vector. Also, you may be making some incorrect assumptions about what the various vector member functions do (for example, invoking clear() won't necessarily cause any memory to be released).   ;  Im was not using zeromemory to clean std vectors, as I said its suppose to be alredy a cleaned vector(and debuging, it is cleaned when it gets on zero memory), zero memory is just cleaning the whole structure..."How are you determining that a memory leak has occurred?"With the debug output for memory allocation:Detected memory leaks!Dumping objects ->{259} normal block at 0x00000000000CF150, 56 bytes long. Data: <    9  =   > 00 00 00 00 39 8E E3 3D 00 00 00 00 00 00 00 00 {252} normal block at 0x00000000000CF370, 84 bytes long. Data: <   9  =    > 00 00 00 00 00 00 00 00 39 8E E3 3D 00 00 00 00 {245} normal block at 0x00000000000CF0B0, 56 bytes long. Data: <  9  => 00 00 00 00 00 00 00 00 00 00 00 00 39 8E E3 3D {240} normal block at 0x00000000000CF230, 56 bytes long. Data: <    9  =   > 00 00 00 00 39 8E E3 3D 00 00 00 00 00 00 00 00 {236} normal block at 0x00000000000CEE90, 84 bytes long. Data: <   9  =    > 00 00 00 00 00 00 00 00 39 8E E3 3D 00 00 00 00 Object dump complete.Can you be more specific? clear dont release memory? Of course it do, it empty the vector, what do you mean?Can you explain me whats going on with the zeromemory at there? Because cutting it out like fastcall said indeed solve the problem..To me it dont make any sense yet...asigning it with default construct A() just fill it with junk values(with is obvious), witch is the motive to me be using zeromemory(but everything wents fine like that )So I just tested and instead of doing zeromemory to actual_A I did with a new struct A, like that://instead of that: ZeroMemory(&actual_A, sizeof(actual_A));//instead of that: actual_A = A();//THIS ALSO SOLVES//do that:A tmp_zeroedA; ZeroMemory(&tmp_zeroedA, sizeof(A));actual_A = tmp_zeroedA;//THIS SOLVES TOO!!Thats magic, explain me please!   ;  vector<int> myVec;Constructing a vector such as done in the code above will create an empty vector with some space reserved.  In other words, myVec already has some space allocated for future elements.ZeroMemory( &myVec, sizeof(myVec) );Among other horrible things, trampling over myVec by turning all its bits to 0 will invoke undefined behavior.  In your case, this undefined behaviors seems that myVec forgets that it already had allocated memory for itself.vector<int> anotherVec = myVec;This calls a copy constructor, which copies all elements inside myVec into anotherVec.  However, since the member for myVec that tracks the number of elements in myVec has been overwritten to 0, this creates an empty vector<int>.  In your example, it is the same as writing:   vector<int> anotherVec = vector<int>();Quote:Original post by Icebone1000Im was not using zeromemory to clean std vectors, as I said its suppose to be alredy a cleaned vector(and debuging, it is cleaned when it gets on zero memory), zero memory is just cleaning the whole structure...You were...  "A" has a vector, so ZeroMemorying "A" will also trample the vector inside it.Quote:Can you explain me whats going on with the zeromemory at there? Because cutting it out like fastcall said indeed solve the problem..To me it dont make any sense yet...This is what's happening:#include <iostream>using namespace std;class Foobar {public:Foobar() {mCount = 0;mData = new int[16];}Foobar( const Foobar& f ) {mData = new int[16];mCount = f.mCount;for ( int i = 0; i < f.mCount; ++i )mData = f.mData;}~Foobar() {delete[] mData;}bool push_back( int val ) {if ( mCount >= 16 )return false;mData[mCount] = val;mCount ++;return true;}public:int*mData;intmCount;};int main() {Foobar bob;bob.push_back( 4 ); // Okcout << bob.mData << endl // Ok<< bob.mCount << endl;ZeroMemory( &bob, sizeof( bob ) );cout << bob.mData <<  endl // Bad!  bob.mData  points to 0!  Previously allocated memory is lost!<< bob.mCount << endl; // Seemingly ok (it zeroed all the elements, didn't it?)// bob.push_back( 5 ); // Ka-boom!  Access violation occurs!Foobar temp( bob ); // Calls copy constructorcout << temp.mData << endl; // Ok!  Although bob.mData points to 0, temp.mData doesn't!cout << temp.mCount << endl; // Ok!}EDIT:Jyk explains it much better![Edited by - _fastcall on May 16, 2010 11:57:27 PM];Quote:Im was not using zeromemory to clean std vectors, as I said its suppose to be alredy a cleaned vector(and debuging, it is cleaned when it gets on zero memory), zero memory is just cleaning the whole structure...If you're using ZeroMemory() to 'clean' a structure that has a member field of type std::vector, then you're using ZeroMemory() to 'clean' a std::vector, which, generally speaking, you shouldn't do.AFAIK, ZeroMemory() sets all the bytes in the specified block to zero. If 'all bytes are set to zero' makes sense as a state for a particular object, then you can use ZeroMemory() to initialize it (I'm not saying you should, but you can). If however 'all bytes are set to zero' might equate to an invalid or internally inconsistent state, then you shouldn't use it to initialize the object.std::vector, for all practical purposes, is an opaque container whose inner workings are implementation-defined. Generally speaking, you don't know whether 'all zeros' is a valid state for an object of type std::vector.For this reason (and maybe others), zeroing memory as a means of initializing objects in C++ is generally discouraged; instead, favor proper initialization via constructors. (Sometimes zeroing is used for technical reasons and/or in low-level code, but this should be the exception, not the rule.)Quote:clear dont release memory? Of course it do, it empty the vector, what do you mean?You're making assumptions here.The standard dictates certain behaviors with respect to std::vector, but other behaviors are implementation-defined.In particular, your typical implementation of std::vector will try to be 'smart' about memory allocations so as to minimize fragmentation and run-time allocation and deallocation costs. This is generally accomplished via low-level memory management techniques (use of 'placement new' and so on), and through conservative use of allocated memory. An implication of this is that vector member functions may not always do what you intuitively expect. So, although it may seem 'obvious' that clear() would release memory, it's not necessarily the case that it will. (The elements of the vector will, however, be destroyed, and the element count will be set to zero.)   ;Quote:Original post by Icebone1000zero memory is just cleaning the whole structure...And the structure contains a vector, which means you're copying zeros over the top of a vector. That is very bad. It doesn't matter if the vector was already empty or not -- there's no way for you to know what overwriting the vector's memory with zeros is going to do. You're lucky it doesn't cause a crash - with many other classes it could!Quote:Can you be more specific? clear dont release memory? Of course it do, it empty the vector, what do you mean?Clear changes the size of the vector to zero, but doesn't necessarily change the capacity of the vector.Even though it's empty, the vector might still contain a pointer to a buffer, so that when you insert something it doesn't have to reallocate that buffer.If you *really* want to release the buffer inside a vector (which you almost never do), you can swap the vector with a default initialised one:vector<foo> myVector(5);{  vector<foo> empty;  myVector.swap( empty );}Quote:Can you explain me whats going on with the zeromemory at there? Because cutting it out like fastcall said indeed solve the problem..To me it dont make any sense yet...In C++ you never use ZeroMemory/memcpy except on POD types. A struct that contains a std::vector is not a POD type.http://stackoverflow.com/questions/146452/what-are-pod-types-in-chttp://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.htmlhttp://en.wikipedia.org/wiki/Plain_Old_Data_Structures   ;  got it! thanks ¦)   ;Quote:Original post by HodgmanIn C++ you never use ZeroMemory/memcpy except on POD types. A struct that contains a std::vector is not a POD type.http://stackoverflow.com/questions/146452/what-are-pod-types-in-chttp://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.htmlhttp://en.wikipedia.org/wiki/Plain_Old_Data_StructuresMinor adjustment: In C++, you never use ZeroMemory, except maybe when solely developing for the Windows platform   ;  Also:  you do not have a memory leak.  The std::vector uses a pooling allocator by default.  The memory pool it uses remains "allocated" at the end of the program, according to many naive tools.  This is not a bug in the library.  It is by design.  It is a flaw in your memory leak detection tools that they report it as an error.   