Click to See Complete Forum and Search --> : STL Vector - delete memory ?


KingTermite
February 2nd, 2003, 11:39 AM
Does the STL vector class delete the allocated memory for its elements when it calls its clear() method or does it just remove them from the vector's list, but leave the memory untouched?

I have vectors storing pointers to allocated memory and would like to ensure the memory is deleted too as it clears the vector (don't want those memory leaks do we).

Thanks in Advance.

Philip Nicoletti
February 2nd, 2003, 12:29 PM
No it does not delete that memory. You need to do it
yourself. Or use some type of smart pointer, such as
boost's shared pointer and the CountedPtr in the
Josuttis book. But not std::auto_ptr

Meyer's "Effective STL" has a good discussion on this:
"Item 7: When using containers of newed pointers,
remember to delete the pointers before the
container is destroyed"


Here is a simple program showing the need to delete:


#include <vector>
#include <iostream>

using namespace std;

class A
{

public:

A(){ia=1;}
~A(){ std::cout << "~A()" << std::endl; }

private:

int ia;
};

int main()
{
vector<A*> v;

A* a = new A;
v.push_back(a);

vector<A*>::iterator it;
for (it=v.begin(); it!=v.end(); ++it)
{
delete (*it); // comment out and destructor is not called
}

v.clear();

return 0;
}

KingTermite
February 2nd, 2003, 02:56 PM
Thank you very much. This is a helpful piece of code.

One more problem. When I want to delete the memory, some of them may have already been deallocated, so when I try to free them I get an unhandled exception.

I tried to do something like:

for (int i=0; i<oVector.size(); i++)
{
try
{
free(oVector.at(i);
}
catch(...)
{
continue;
}

} // end for


It doesn't work. I still get unhandled exception errors. Any ideas?

Andreas Masur
February 2nd, 2003, 03:45 PM
Originally posted by KingTermite
Thank you very much. This is a helpful piece of code.

One more problem. When I want to delete the memory, some of them may have already been deallocated, so when I try to free them I get an unhandled exception.

The standard C functions 'malloc()' and 'free' do not throw any exception at all.

If you really need to delete an instance without deleting the associated pointer inside the vector you should set the pointer to 0 at the same time. In this case you can simply determine whether to delete the associated object while destructing the vector or not.

I would also suggest that you use 'new' and 'delete' instead of the old C style allocation functions. Then you also do not need to do the check before freeing it...thus

// C style
if(pPointer)
free(pPointer);

// C++ style
delete(pPointer);

However...I would suggest that you delete the associated pointer from the vector at the same time you delete the instance of the object...

KingTermite
February 2nd, 2003, 05:47 PM
I fixed it another way (I wanted to stick with the original way).

I had to reallocate a new string for each that was stored in the vector.

I had to keep them in the vector, even if their originals are deleted because it's a hash table that is being used to ensure there are no duplicates. I have to keep them for that purpose, so I had to fix it by making a copy. :(

Darn, tree searching algorithms. Pain in the butt.

Paul McKenzie
February 2nd, 2003, 06:45 PM
Originally posted by KingTermite
I fixed it another way (I wanted to stick with the original way).

I had to reallocate a new string for each that was stored in the vector.
If you use std::string instead, you don't need to reallocate anything -- copying items that contain std::strings will automatically invoke the copy for the strings.

As Andreas mentioned, since this is C++, you should attempt to make your program fit the C++ paradigm. For example, replacing the malloc and free with new and delete. You started by using std::vector, but you may as well look at the other parts of your code as well.

One big reason to drop using malloc and free is that malloc() and free() can only be used safely on structures that contain ints, doubles, floats, chars, i.e. the "simple" (also called POD or Plain Old Data) data types. If your object contains std::strings, CString, or any class that has a non-trivial constructor or destructor, you are invoking undefined behavior by utilizing 'C' functions such as malloc(), free(), memcpy(), memset(), etc on those objects. Creating, copying and assigning is done by the constructor, copy constructor, and assignment operator.

Regards,

Paul McKenzie

KingTermite
February 2nd, 2003, 07:10 PM
Thanks. I'll keep it in mind.

I'd prefer to be doing this in an even more object-oriented language like java, however I am working with two partners which only know ansi-C. I had to beg to let them allow me to make it cpp just so I could just the vector class and not re-write my own linked list function structure or something similar.

I might try the std::string. To be honest, I'm not that familiar with c++. I've seldom used it. I kind of went from C straight to Java, so I don't know all standard classes available and such.

I appreicate the tips though, guys. I may try the string class you mentioned.

DanM
February 3rd, 2003, 02:22 AM
Just a small addition: catch(...) will not only catch C++ exception but also access violations, breakpoints...
You shouldn't use catch(...) unless you have a special purpose.

Dan

Gabriel Fleseriu
February 3rd, 2003, 02:44 AM
Originally posted by DanM
Just a small addition: catch(...) will not only catch C++ exception but also access violations, breakpoints...
You shouldn't use catch(...) unless you have a special purpose.

Dan

Sorry, but I don't think so. As far as I know, access violations and breakpoints are SE, not C++ exceptions. A catch(...) won't catch them, altough there are mechanisms that allow translating a SE into a C++ exception.

On the other hand, I agree: one shouldn't use catch(...) without good reason.

DanM
February 3rd, 2003, 03:15 AM
I used catch (...) to catch access violations and dump stack traces many times before so I assume I'm right :)

Anyway, just try to run the following code snippet using the VC++ compiler and you will see the output:

try
{
int *p = 0;
*p = 1;
}catch (...)
{
cout << "Exception caught !" << endl;
}

Dan

Gabriel Fleseriu
February 3rd, 2003, 03:28 AM
Hummmm. I used following code to test this:

#include <iostream>
int main()
{
try
{
int *p = 0;
*p = 1;
}catch (...)
{
std::cout << "Exception caught !" << std::endl;
}
char c;
std::cin>>c;
return 0;
}

The debug build indeed prints "Exception caught !". The release build gives me an unhalted exception (access violation). I am pretty convinced that the access violation is a SE and cannot be caught with a C++ catch(...). On the other hand, I don't have a good explanation on why the debug build behaves like it does. I will do a bit of research and will post an update here.

Anyway, Dan, you have a point. I think it is worth to understand what's happening here, even if it is a bit off-topic, considering the OPs question :)

Gabriel Fleseriu
February 3rd, 2003, 04:27 AM
I skimmed thru MSDN, and yes, Dan is correct: VC++ can catch a SE with a catch(...) block -- at least this is what the documentation sais.
Dan, you were right, I was wrong :).

OTOH, I am still wondering why the access violation isn't caught in release mode for that small test program of mine.

However, I think that this is an implementation detail. Standard C++ doesn't know about SE -- correct me if I am wrong.

Mick
February 3rd, 2003, 07:55 PM
Originally posted by Gabriel Fleseriu
OTOH, I am still wondering why the access violation isn't caught in release mode for that small test program of mine.


You have to install your own SetUnhandledExceptionFilter().

After calling this function, if an exception occurs in a process that is not being debugged, and the (first-chance exceptions generally) exception makes it to the unhandled exception filter (top level filter that is present for all win32 threads/processes), that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter. Probably setting EXCEPTION_CONTINUE_EXECUTION would invoke your catch(...) but I don't recall that behaviour off-hand.

There's a small (but good) section that explains this (win32 specific) in windows nt/2000 native api reference -Gary Nebbett.

I can quote the section that pertains to this if you want, but I don't want to type a couple of paragraphs unless I have 2....

DanM
February 3rd, 2003, 11:13 PM
Here is what MSDN says:

"If a C exception is raised in a C++ program, it can be handled by a structured exception handler with its associated filter or by a C++ catch handler, whichever is dynamically nearer to the exception context."

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_core_Exception_Handling_Differences.asp

Dan

Mick
February 4th, 2003, 12:27 AM
Ahh Yep that will do.
Which reminds me, perhaps something about exception debugging should be in the FAQ. Maybe a whole section on just plain debugging..hey I got an assert help me!!!, catching memory leaks, using windbg, making sure you have the latest symbols installed...yada..yada..yada... ahh but that's way off topic I guess and probably already noted somewhere....;)