views:

440

answers:

5

Hi all,

I would like my class to have a static pointer to a dynamically allocated region of memory. I understand how to initialize it - in my case I will initialize it when the first object needs it. However, I don't know when/where in the code to free it. I'd like to free it when the program terminates.

I might be able to free the pointer in my objects' destructor, but then I'd have to maintain an object count to see if it's safe to free when the object is the last object in use.

Is there a more elegant way to do this?

Please let me know.

Thanks, jbu

+5  A: 

You have two solutions here:

  1. Don't delete delete it (you're in C++, you use new and delete, right? ;) ). Almost all OSes today will "free" the memory allocated by the application anyway once it's finished. But that's not a good solution, that make memory leaks hard to detect for example.
  2. Encapsulate your pointer into a class (as member), then use this class as the type of your static. That way, you know the class destructor will be called at the end of the application. You then just delete your data in the destructor and the work is done and clean. That's the power of RAII.

I suggest you do 2, that's a really clean way to do it.


Here is a simple example. Instead of doing this

static Thing* things = new Thing(); // or whatever way to initialize, here or in a specific function

You will do that :

class ThingManager // or whatever name you like
{
public:
   ThingManager( Thing* thing ) : m_thing( thing ) { }//or create it here? whatever solution suits your way of creating the data

   ~ThingManager() { delete m_thing; } // THAT's the important part!

    Thing* instance() const { return m_thing; } // or whatever accessor you need, if you need one

private:
    Thing* m_thing;
};

and then

static ManagedThing thing; // now i can access it via thing.instance() 

When the program ends, the static variable (that is not pointer anymore) will be destroyed and it's destructor will be called to do that.

It's written just to give you an idea of how you can do that.

Klaim
Sorry, I'm very new to C++. When you say "the class destructor will be called at the end of the application" are you saying there's an object destructor and a static class destructor? Also, what's RAII?
jbu
RAII : http://en.wikipedia.org/wiki/Resource_Acquisition_Is_InitializationYou should learn about the default functions of all classes.
Klaim
RAII is an unfortunate term, because it isn't very descriptive; see http://en.wikipedia.org/wiki/RAII
Mark Ransom
+1 We really should start to use another term for that, it would help adopting the paradigm for newbies.
Klaim
+1  A: 

You can declare you static variable as a smart pointer, then when the program finish the pointer allocated will be freed.

coelhudo
A: 

i would define a static counter in the class to track object instances count as the destructor get execute it decrement the counter and if counter== 0 free the memory too .. just as you

luca
+3  A: 

From the OS perspective, there's no real point in freeing memory as your program terminates, all that does is slow termination down. Termination of your application tears down your entire address space, it will free everything you allocate on the heap all at once. explicitly calling free on app shutdown is just shuffling pointers in the heap that will get thrown away anyway.

The main reason why we try so hard to free everything explicitly is to be sure that we aren't leaking memory and our memory footprint doesn't grow forever.

But if you can be certain that this is static, that there will be only one, and that you can't safely free it until all of your other objects have been freed, this is a case where it might be better just to let application termination take care of it for you.

John Knoeller
Thanks for the response. I always thought that memory leaks will make the OS hold on to reserved/unfreed memory even after program termination.
jbu
@jbu: It wouldn't be a very good OS if it did that. ;)
John Knoeller
Althought that will mask other memory leaks with some memory-leak detection tools, so it's not recommanded anyway.
Klaim
There is still a benefit to releasing memory before shutdown - it makes real memory leaks easier to find. If you use a tool to track allocations, anything you don't delete will be noise you have to wade through.
Mark Ransom
@John: This argument only holds true for OSes with virtual memory managers. Some real-time/embedded OSes, for example, have no such manager. Leaking at termination would definitely be a problem on those platforms. Relying on the OSes VMM to do the cleanup is a bad habit to develop, IMO.
Void
@Void: it doesn't technically rely on the OS having a VMM. I have used a system with no virtual memory, but where `malloc` and `free` added/removed the block to a list of allocations. Cost 8 bytes and an interrupt off/on cycle per allocation, but allowed the OS to free them all on process termination. Per-process heaps can achieve the same thing (I think the reason this system didn't use one was because they make it much harder to release freed memory back to the OS for use by other processes, which was desirable on this system).
Steve Jessop
@Steve: I haven't seen OSes that do that. Thanks for pointing out such OSes exist!
Void
@Void: This was a pretty minority thing, an embedded OS where most low-level code was written in a custom assembler. Applications written in C were considered "high-level", and the low-level allocator was available to them if they were willing to take on responsibility for their own memory management. That's why it was acceptable to impose the overhead on malloc/free.
Steve Jessop
+7  A: 

Throw it in a smart pointer. It will have static lifetime and be destroyed after main returns:

static std::auto_ptr<T> thePointer;

Another option is to register your own atexit function:

// static
void YourClass::freePointer(void)
{
    delete getPointer();
}

// static
T* YourClass::getPointer(void)
{
    if (!thePointer)
    {
        thePointer = new T;
        atexit(freePointer);
    }

    return thePointer;
}

Which will have the same effect. Another option you already mention is to keep a static counter. Note you can actually wrap that up pretty effectively.

GMan
Alexandrescu uses `atexit` in the implementation of his `Loki::Singleton`. This way he ensures that the methods that frees the pointer also resets its state to `0` so that it can be reallocated if necessary (case of the `Phoenix` lifetime policy). Personally I think an `auto_ptr` or even better `unique_ptr` much less trouble.
Matthieu M.