16

What happens to a static variable when returned as a reference and passed as a pointer directly to another function? Obviously, the variable persists after the function returns, but something about this whole concept just bothers me. At which point is the memory on the data-sequent, occupied by the static variable, freed? Does the runtime magically notice when I no longer need it, like some kind of garbage collection?

To give an example:

SDL_Rect* XSDL_RectConstr(int x, int y, int w, int h)
{
    static SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;

    return ▭
}

void mainLoop()
{
    while(isRunning)
    {
        pollEvents();
        SDL_BlitSurface(someSurface, XSDL_RectConstr(0, 0, 100, 100), screen, NULL);
        SDL_Flip(screen);
    }
}

What happens to rect after SDL_BlitSurface() returns? I can't see when it would be freed. Wouldn't this be some kind of memory leak then?

David G
  • 94,763
  • 41
  • 167
  • 253
Byzantian
  • 3,208
  • 4
  • 27
  • 31

3 Answers3

13

At which point is the memory on the data-sequent, occupied by the static variable, freed? Does the runtime magically notice when I no longer need it, like some kind of garbage collection?

It would be freed at program exit, not sooner. Also, it's guaranteed that destructors would be called.

hate-engine
  • 2,300
  • 18
  • 26
  • So it will still hog up huge amounts of memory, given that it's running in an infinite loop, right? Or does it overwrite itself every time XSDL_RectConstr() is called? Also, SDL_rect is a struct, not a class, and thus does not have a destructor, but I guess that is irrelevant. – Byzantian Nov 16 '12 at 21:27
  • 1
    It overwrites itself, that's the problem. Every struct (and every class) has a destructor, if you don't write one a default one is generated. – john Nov 16 '12 at 21:30
  • 3
    It doesn't "overwrite" anything. It's the same object. The only magic here is that it isn't constructed until the first time you enter that function; aside from the usual scoping rules, there is nothing different about this than a `static` defined in namespace scope. It's like a static "member" of the function. – Lightness Races in Orbit Nov 16 '12 at 21:31
  • @LightnessRacesinOrbit Yes, so a second call to `XSDL_RectConstr` overwrites the values that the first call to `XSDL_RectConstr` set. – john Nov 16 '12 at 21:32
  • 2
    @john: Right, that, ok. But "overwrite _itself_" is not correct. The following lines in the function? Sure, they are assigning values to the members of the same, original object. – Lightness Races in Orbit Nov 16 '12 at 21:50
6

There's no memory leak, but it's a really, really bad idea. Suppose you wrote some code like this

SDL_someFunction(
    XSDL_RectConstr(0, 0, 100, 100), 
    XSDL_RectConstr(20, 20, 30, 30)
);

Because you have only one static rectangle, SDL_someFunction is not going to get the different rectangles that it looks like it's going to get. Instead you will get the same rectangle twice.

john
  • 85,011
  • 4
  • 57
  • 81
5

rect will not be freed upon return from SDL_BlitSurface, but it would not be a memory leak either: it's in the static storage, so there is nothing to "leak". The object will stay in memory for as long as your program is running.

The biggest downside to this happens when you start multithreading: your static variable runs a risk of being modified from multiple threads concurrently, which is something that you would rather avoid.

Destructors for initialized objects of static storage duration (declared at block scope or at namespace scope) are called as a result of returning from main and as a result of calling exit.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I could just fix the multi-threading issue by using a mutex lock around the function, correct? – Byzantian Nov 16 '12 at 21:33
  • @cyberpunk_ Yes, this is correct. The mutex needs to be around the call of the function and encompass the code where you use the value from the static variable along with the invocation itself. – Sergey Kalinichenko Nov 16 '12 at 21:35