views:

161

answers:

7

I have a few arrays and a resource that needs deletion, the value of these variables are retained throughout the lifetime of the program and they are only used in a single function so it naturally fits into static variables:

void func() {
    static GLfloat arrs[4] = {1, 1, 1, 1};
    static GLUquadric* quad = gluNewQuadric(); // delete with gluDeleteQuadric(quad)
    //... other codes ... 
}

However, if I used static, I would have trouble with delete-ing these resources since I cannot access these variables from outside the function. I can make these globals, but I would like to avoid that if possible.

So the question is:

  1. Is arrs[] stack- or heap-allocated? And so, would I need to delete it?
  2. In the case of GLUquadric, obviously the compiler would not know how to properly delete it, for now I've used a RAII wrapper class which worked beautifully, but I'm looking if there's an even simpler approach.

valgrind complained for not releasing the GLUquadric, and I guess I'd just clean it up rather than silencing valgrind even though the program should be about to end anyway when I will release them and these resources are probably(?) released when the program ends.

+2  A: 
  1. No need to delete arrs[], it's not been allocated on the heap. It is not on the stack either, it's in the data segment somewhere, and part of your static program data and will go away when the process does.

  2. On the heap but generally not to worry about. This sort of allocating heap during static initialisation is not very good, but it only bytes you if you need any destructor calls in the end (to get rid of external resources etc.).

Edited: I'd still worry about that heap object. especially if it comes from some library; you never know what it is up to internally, it may have locked up some hardware resources or similar. You can't do anything here with smart pointers etc., but if you really need this to be allocated this way, it may be worth registering the deallocation with the atexit() function or similar. Or put the whole thing into a global static singleton object with a destructor. You only have nothing to worry about if you know that the object only contains data, i.e. don't worry about your heap.

Alexander Rautenberg
Always worry about leaked memory. Doing otherwise is just silly especially since the problem is so easy to solve.
Martin York
There's no problem to solve. Values of static variables won't go away before the program terminates, there is no possible point in the process lifetime where deallocation makes sense, the heap itself is being destroyed on termination, the concept of a memory leak does not apply.
Alexander Rautenberg
Would GLUquadric not be considered external resources? since it should be deleted using gluDeleteQuadric instead of the regular delete operator. And I don't have any idea of its possible interaction with the graphic driver or the X server (esp. whether or not not releasing it could produce a behavioral leak on their side). It's not explained on OpenGL references either of the consequences of not calling gluDeleteQuadric() after a gluNewQuadric().
Lie Ryan
nevermind, just noticed your Edited section; anyway, my previous RAII wrapper's destructor does gets called at program end, so for now it's probably the best solution for #2. Unless I can make sure that gluQuadric is guaranteed to be a pure client-side operation, in which case I can just do away with all of it and not care.
Lie Ryan
+1  A: 

By your description, I am assuming that these statics are declared inside of the function that uses them. In that case, you don't need to delete them. In fact, you couldn't delete them if you wanted to. Since the function wouldn't work properly if the static data wasn't available, you can't delete it. They are not stack variables since they outlive the lifetime of the function.

bta
+1  A: 

Use an auto ptr:

int myFunc()
{
    static GLfloat                   arrs[4] = {1, 1, 1, 1};
    static std::auto_ptr<GLUquadric> quad    = gluNewQuadric();

    // Do Stuff
}

The static variable is initialised on first use.
Then it is destroyed when the application is terminated. Because it is a smart pointer it will delete the pointer.

1: Is arrs[] stack- or heap-allocated? And so, would I need to delete it?

Neither.
And no you don;t need to delete it.
It has static storage duration, this just means that it will live until after main exits then be destroyed with the other static storage duration objects (in reverse order of creation).

2: In the case of GLUquadric, obviously the compiler would not know how to properly delete it, for now I've used a RAII wrapper class which worked beautifully, but I'm looking if there's an even simpler approach.

No. Just use a standard one to make it as simple as possible.

Martin York
Being a smart pointer, it would deallocate the underlying raw pointer memory when it goes out of scope, it is not related to the lifetime of the process. I doubt it'll do anything useful in this scenario.
Alexander Rautenberg
@Alexander Rautenberg: Its perfect for this scenario: a static function variables have a lifespan of the application they are not destroyed when the function exits (as explained above) but will be destroyed after main() exits. As a result they are perfect for this situation as they are lazily created (on first use) and guaranteed to be destroyed (in reverse order of creation with all other objects of static lifetime).
Martin York
The concept is sound though: it wouldn't be too hard to implement a custom auto_ptr that calls the correct glu* function to free the memory "properly".
Matthew Iselin
`auto_ptr` isn't correct for this situation. `auto_ptr` always uses `delete`. In this case the pointer needs to be released with a call to `gluDeleteQuadric`. This scenario needs a "smarter" smart pointer.
Charles Bailey
A boost::scoped_ptr with a custom deleter would be appropriate here.
karunski
@MAtthew Iselin, @Charles Bailey, @Karunski. The need to call a custom free routine was added after I answered the question.
Martin York
Fair enough; it must have been a five minute edit.
Charles Bailey
@Martin York. Getting your point now.
Alexander Rautenberg
A: 

The basic rule is that we should delete only whatever we allocated. If we allocated with new, release the memory with delete. If we allocated with new[], release the memory with delete[].

So for

Q1. No, don't delete. We never new'ed it

Q2. Yes, we need to delete assuming the function allocated it. However the problem is that by looking at Quadratic it is tough to know if the returned pointer is newed for only one 'Quadtric' or an 'array of Quadtric', or is it just a pointer to some static variable somewhere. So use delete or delete[] accordingly if you allocated memory dynamically.

Chubsdad
A: 

As for the curious and future reference, this is my RAII template:

template <typename T, T* constructor(), void destructor(T*)>
class Managed {
    private:
        T* value;
    public:
        Managed() {
            value = constructor();
        }
        ~Managed() {
            destructor(value);
        }
        T* operator*() {
            return value;
        }
};

and it is used like this:

typedef Managed<GLUquadric, gluNewQuadric, gluDeleteQuadric> MGLUquadric;
static MGLUquadric quad = MGLUquadric();
gluSphere(*quad, 3.0f, 20, 20);
Lie Ryan
+1  A: 

As your "delete" function is a simple single parameter function you can use it directly with a TR1 (or boost) shared_ptr with a custom deleter.

void func()
{
    static std::tr1::shared_ptr<GLUQuadric> quad(gluNewQuadric(), gluDeleteQuadric);
    // ...
}
Charles Bailey
I won't be able to use C++0x or TR1 features for the moment, and probably wouldn't want to add boost dependency just for this, but thanks anyway, shared_ptr would be useful for future reference.
Lie Ryan
A: 

Q1 and Q2: don't do it!. You cannot use std::auto_ptr<GLUquadricObj> since it is a resource which needs to be deallocated by a specialized deleter gluDeleteQuadric. Generally, in a state driven engine like OpenGL and GLU don't use statics - well don't use them ever, but in OpenGL context, that's especially dangerous.

Now again, seriously:

Q1. don't do it. There is no gain at all in storing a static 4-element array of integers. Define it locally where you need it. My advice: don't use c-style arrays, instead say:

const std::array<int, 4> tArray = {1, 1, 1, 1};

Q2. RAII advice given above is good, but you need a RAII wrapper which supports custom deleters:

std::shared_ptr<GLUquadricObj> 
 tMyQuadric(glCreateQuadric(), glDeleteQuadric);

Now use it at will, it will be closed and destroyed automatically, when they go out of scope and the program has no reference to it. Oh, I see the custom RAII wrapper above would also work, but please: do yourself and your followers and co-workers a favour: use standard library constructs.

paul_71
is std::array a standard C++? I can't find it mentioned anywhere in either http://www.cplusplus.com/ or http://www.cppreference.com/; ah... it seem it's a C++0x feature, which I can't use at all due to some artificial restriction I have absolutely no control with.
Lie Ryan
No, strictly speaking it's part of TR1. I know that kind of restrictions well... But if you can use TR1 (either native, or via boost) then you can also use std::tr1::array
paul_71