views:

387

answers:

6

Can anybody explain how to free memory of a static member Variable? In my understanding it can only be freed if all the instances of the class are destroyed. I am a little bit helpless at this point...

Some Code to explain it:

class ball
{
    private:
    static SDL_Surface *ball_image;
};
//FIXME: how to free static Variable?
SDL_Surface* ball::ball_image = SDL_LoadBMP("ball.bmp");
+7  A: 

The pointer itself will be around until the program shuts down. However, what it points to is fair game. You can free that at any time.

If what you're worried about is memory leaks, then you have a few options that I see:

  1. Just let it leak. All the memory from the program will be released when it shuts down. However, if you need more than just the memory being freed (like you want a destructor to run), then that's not such a good idea.

  2. Have a static member variable which keeps track of how many instances of the class have been created. Free the memory when it reaches zero and reallocate it if it goes above 0 again.

  3. Have a function of some kind which runs when the program is shutting down and have it worry about freeing the memory.

  4. If you can, make it so that it's not a pointer anymore. If it's not a pointer, you don't have to worry about it.

  5. Use a smart pointer or auto_ptr. That way, when the pointer itself is destroyed, the memory will be taken care of.

Personally, I'd advise 4 if you can and 5 if you can't, but you have several options.

Jonathan M Davis
Deleted my answer, which was similar to yours but not as thorough.
Nate
My idea was to do it like you describe in 2. but I thought there could be a better way.What is a smart pointer? Never heard that before. Sounds like garbage collection..
A smart pointer is an object which holds a pointer, allows you to use it as if it were a pointer, and frees that memory for the pointer when it's destroyed (frequently done by reference counting to see whether there are any references left to the pointer). It's similar to garbage collection in that it manages the memory for you, but it's a separate concept. I added a link to the boost implementations. There's plenty of info online on them - including at wikipedia. Also, if you just search smart pointers here at SO, you'll get a number of questions related to them.
Jonathan M Davis
Also, when you research smart pointers, note that `auto_ptr` has weird semantics and is deprecated. Use `std::unique_ptr` (in the brand new C++0x compilers) or one of the [Boost Smart Pointers](http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm).
Nate
+3  A: 

The static member variable in this case is a pointer. You can't free it, but you can free what it points to:

SDL_FreeSurface(ball_image);

You might then want to set ball_image to 0, to record the fact that you no longer have an image.

it can only be freed if all the instances of the class are destroyed

If by "the class" you mean ball, then no. Static members of ball continue to exist regardless of how many instances of ball there are. The only way a static member might be destroyed before program exit is if you do some (implementation-dependent) thing like unloading the dll which contains the class. But in this case the static member is just a pointer, so (1) destroying it will just destroy the pointer, not the pointee, and (2) there is no need to destroy a pointer anyway, it doesn't occupy significant resources.

Steve Jessop
+1  A: 

If you must have the static member pointing to heap-allocated memory, I would make a member a smart pointer.

Adam
+1  A: 

A static member exists completely independently of all instances of the class it is a member of. You can delete the pointer at any point in the program. Whether this makes sense semantically, is another issue, of course.

anon
+1  A: 

I agree with Jonathan M Davis' answer, but another option you could consider is pulling your images and other resources out of your "domain objects" and into a ResourceManager class, or something along those lines.

The ResourceManager could either be static, or instance-based, and would provide the logic to load and delete resources, needed by the rest of our application.

Classes needing resources could just hold a reference or a pointer to the global resource manager, and request resources from the manager, rather than managing them themselves.

Andy White
+6  A: 

From the sound of it, you don't really want a pointer at all. In fact, since this is coming from a factory function in a C library, it isn't really a "first-class" C++ pointer. For example, you can't safely delete it.

The real problem (if there is one) is to call SDL_FreeSurface on it before the program exits.

This requires a simple wrapper class.

struct smart_sdl_surface {
    SDL_Surface *handle;

    explicit smart_sdl_surface( char const *name )
        : handle( SDL_LoadBMP( name ) ) {}
    ~smart_sdl_surface()
        { SDL_FreeSurface( handle ); }
};

class ball
{
    private:
    static smart_sdl_surface ball_image_wrapper;
    static SDL_Surface *& ball_image; // reference to the ptr inside wrapper
};
smart_sdl_surface ball::ball_image_wrapper( "ball.bmp" );
SDL_Surface *&ball::ball_image = ball::ball_image_wrapper.handle;

When the program initializes, the constructor is called and the file is read. When the program exits, the destructor is called and the object is destroyed.

Potatoswatter