Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C++ (http://www.programmingforums.org/forum15.html)
-   -   STL and memory management (http://www.programmingforums.org/showthread.php?t=12922)

rwm Apr 2nd, 2007 7:04 AM

STL and memory management
 
hi,

I have this question about using STL with dynamically allocated memory.

say for example I do this:

:

list<int *> mylist;

and i do stuff on the list - i.e. create pointers to new memory and operate on it.

suppose the time comes to get rid of all that memory, is it fine to use the erase method on the list?

i.e.

:

list<int *>::iterator start = mylist.begin();
list<int *>::iterator end = mylist.end();
mylist.erase(start,end);


or must i iterate over the list and explicitly delete memory as i go along???

grumpy Apr 2nd, 2007 8:12 AM

You must iterate over the list and delete memory as you go. From what you say, an example would be this;
:

#include <list>

int main()
{
    std::list<int *> mylist;

    // initialise list entries

    for (int i = 0; i < 10; ++i)
    {
        int *temp = new int;
        *temp = i;
        mylist.push_back(temp);
    }

    // monkey around with mylist

    //  to release

  std::list<int *> start = mylist.begin(), end = mylist.end();

    // erase individual elements first

  for (std::list<int *> i = start; i != end; ++i)
      delete (*i);

  mylist.erase(start, end);

    return 0;
}

A basic rule of C++ is that, if you explicitly allocate memory with operator new you must ensure it is explicitly released using the corresponding form of operator delete. Failure to do otherwise results in either a memory leak or undefined behaviour.

Unlike some other languages, C++ does not employ a garbage collector unless you deliberately find one and use it in your program.

rwm Apr 2nd, 2007 8:23 AM

hey Grumpy!

thanks for the reply!

I was just wondering if STL freed dynamically allocated memory... appears not!

ok so now i know that any call to new must be removed by hand using delete - or by garbage collection!

grumpy Apr 2nd, 2007 10:57 AM

Quote:

Originally Posted by rwm (Post 126102)
I was just wondering if STL freed dynamically allocated memory... appears not!

The STL containers allocate memory internally, and free memory the memory that they allocate dynamically. But if you store a pointer to dynamically allocated memory in a container, the container will not clean it up for you.

rwm Apr 2nd, 2007 11:06 AM

yeah i already got that!

Game_Ender Apr 4th, 2007 7:40 PM

Unless you have the Boost Pointer Container library. The only catch here is that it manages the memory for you, so when the list it destroyed all the objects it holds are deleted. So if you are storing pointers to an object in the pointer container it will become invalid.

Ooble Apr 6th, 2007 8:47 AM

Doesn't the auto_ptr class in the standard library do the same thing?

grumpy Apr 6th, 2007 10:21 AM

Both the Boost Pointer Container Library and std::auto_ptr invoke operator delete to release dynamically allocated memory. Neither provides a means of ensuring that dynamically allocated memory pointed at by some raw pointer is automatically released.

Game_Ender Apr 6th, 2007 3:47 PM

What? Of course they do, that is what they are for. You give them the raw pointer and they will release the memory for you as the spec says. Of course no library is going to give you garbage collection of an arbitrary raw pointer.

Example:
:

  1. #include <iostream>
  2. #include <memory>
  3.  
  4. struct A
  5. {
  6.     A(int _val) : val(_val) {}
  7.     ~A() { std::cout << "A: " << val << " deleted" << std::endl;}
  8.     int val;
  9. };
  10.  
  11. int main()
  12. {
  13.   A* raw_ptr = new A(1);
  14.  
  15.   {
  16.     // Hand off raw pointer
  17.     std::auto_ptr<A> managed(raw_ptr);
  18.   }
  19.   // auto_ptr now out of scope and object is deleted
  20.  
  21.   return 0;
  22. }
  23.  
  24. // Prints:
  25. // A: 1 deleted


Jimbo Apr 6th, 2007 4:08 PM

There is still an issue with your use of the auto_ptr, demonstrated with a slight change to your program:
:

#include <iostream>
#include <memory>

struct A
{
    A(int _val) : val(_val) {}
    ~A() { std::cout << "A: " << val << " deleted" << std::endl;}
    int val;
};

struct B
{
  A* a;
  B(int val) {
    a = new A(val);
  }
  ~B() { std::cout << "B: " << a->val << " deleted" << std::endl;}
};

int main()
{
  B* raw_ptr = new B(1);

  {
    // Hand off raw pointer
    std::auto_ptr<B> managed(raw_ptr);
    managed->a->val = 24;
    std::cout << managed->a->val << std::endl;
    std::cout << raw_ptr->a->val << std::endl;
  }
  // auto_ptr now out of scope and object is deleted
  std::cout << raw_ptr->a->val << std::endl;
  // delete B would also yield a seg fault...

  return 0;
}

output:
:

$ ./a.out
24
24
B: 24 deleted
Segmentation fault

This might follow the spec, but seems quite dangerous to use in a complex program...


All times are GMT -5. The time now is 2:11 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC