Search code examples
cfreesdl-2

How to correctly free resources allocated by SDL_ttf?


I followed the advices in a previous question and solved a problem of loading a file into memory. However, I found a problem when I free the resources. If I try to free the TTF_Font file before freeing the structure which holds it, the program crashes.

I believe it occurs because double Free(). Free() twice results undefined behaviour.

Accordingly to the documentation, TTF_CloseFont frees BOTH font pointer and the font itself. I suspected that when this occurs, the SDL_RWclose would free an already freed pointer, so it crashes. But when SDL_RWclose frees one of the resources freed by TTF_CloseFont, the font itself, it does not occurs. Another indication to me of undefined behaviour

More info: the order which the ptr_mem_buff (where the font is stored) is freed does not affect the crash (in my environment).

Also, set the pointers to nullptr should have solved, as free(nullptr) results nothing. But the program still crashes even after setting the ptr_Font to null after TTF_CloseFont(ptr_Font);

How should I correctly free these resources?

Code snippet:

    ptr_str_rwops = SDL_RWFromFile("IMG/FreeMono.ttf", "rb");
        var_size_of_file = SDL_RWsize(ptr_str_rwops);
        ptr_mem_buff = calloc(1, var_size_of_file);
        SDL_RWread(ptr_str_rwops, ptr_mem_buff, 1, var_size_of_file);
        SDL_RWclose(ptr_str_rwops);

    ptr_str_rwops2 = SDL_RWFromConstMem(ptr_mem_buff, var_size_of_file);
        ptr_Font = TTF_OpenFontRW(ptr_str_rwops2, 1, 72);
            ptr_Superficie_texto = TTF_RenderText_Solid(ptr_Font, "Hello World", str_SDL_colour);

    /*CUT UNRELATED CODE*/

//  Example 1:  works fine (in my environment, but I suspect undefined behaviour)
    SDL_RWclose(ptr_str_rwops2);
    free(ptr_mem_buff);
    TTF_CloseFont(ptr_Font);

//  Example 2: crashes everytime, I believe exist double Free()

    TTF_CloseFont(ptr_Font);
    SDL_RWclose(ptr_str_rwops2);
    free(ptr_mem_buff);

// Another approach:

    TTF_CloseFont(ptr_Font);
    ptr_Font = nullptr;
    SDL_RWclose(ptr_str_rwops2); // still crashes
    free(ptr_mem_buff);

Solution

  • This call

    ptr_Font = TTF_OpenFontRW(ptr_str_rwops2, 1, 72);

    tells TTF to dispose of the RWOps stream (that's what the 1 means). You don't have to close that stream because the call to TTF_CloseFont() will do that. You DO have to free the ptr_mem_buff though, because the RWOps stream will not do that.