Memory Leak with SDL Multiline Text

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
jmcintyretech
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Thu Mar 28, 2013 1:02 pm

Memory Leak with SDL Multiline Text

Post by jmcintyretech »

*********
Last edited by jmcintyretech on Fri Mar 18, 2016 10:06 am, edited 1 time in total.
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: Memory Leak with SDL Multiline Text

Post by eatcomics »

I know I've run into this same issue. I don't believe I ever found a fix, but it seems to be a common thing

I've never had any luck using SDL_TTF, hopefully someone can come along and inform us both.

http://sdl.5483.n7.nabble.com/TTF-Rende ... d6840.html

And yes, if the text surface will be generated each frame, you definitely want to free it each frame.

Edit: Also I see your using Text_Surface as a local variable. Make sure you're in the proper scope when freeing that surface.
Image
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Memory Leak with SDL Multiline Text

Post by dandymcgee »

I use this in all of my C++ projects now: https://vld.codeplex.com/
Visual Leak Detector is a free, robust, open-source memory leak detection system for Visual C++.

It's pretty easy to use. After installing it, you just need to tell Visual C++ where to find the included header and library file.

Then it can be used with any C/C++ project simply by adding the following line to your code:
#include <vld.h>

When you run your program under the Visual Studio debugger, Visual Leak Detector will output a memory leak report at the end of your debugging session. The leak report includes the full call stack showing how any leaked memory blocks were allocated. Double-click on a line in the call stack to jump to that file and line in the editor window.

It's a very effective way to quickly diagnose, and fix, memory leaks in C/C++ applications.
You include the header, run the program, and check the output window for any reported leaks. It obviously won't catch everything but it's pretty damn useful.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Memory Leak with SDL Multiline Text

Post by Nokurn »

jmcintyretech wrote:First I added the line that frees the SDL surface before starting the next loop. The program runs fine but the memory issue still occurs.
This is the correct thing to do.
jmcintyretech wrote:Next I tried declaring the const char* that I pass to the SDL_RenderText_Solid function as:
const char* before_newline_char = new char;
rather than:
const char*;
and then deleting it on each loop to free up the memory:
delete before_newline_char;
This completely crashes the program.
This is invalid. std::basic_string::c_str() returns a pointer to a C string that is owned by the basic_string. This pointer is typically the string, which the basic_string acts upon, although this isn't guaranteed by the standard. The pointer is valid until the basic_string is modified (ie, a non-const method is called, with a few exceptions) or destructed. You do not own the string and should not concern yourself with its deletion. If you allocate before_newline_char using new char, you are allocating one byte of memory and then immediately losing the pointer by overwriting it with the pointer given to you by c_str(). Thus, the call to delete acts upon the pointer owned by basic_string. The basic_string class still behaves as if the pointer is valid and likely attempts to delete it upon destruction, resulting in a crash due to double-freeing memory.

Side note, your comment, "Make a const char copy of the line and blit the surface," is incorrect. The c_str() method does not return a copy of a basic_string's contents. If you call it twice in succession, both calls will return the same exact location in memory. You're simply obtaining a pointer that you may use with C APIs, such as TTF_RenderText_*.

As for your leak, the code you have provided is correct. It is likely that your problem lies elsewhere, either in code surrounding your draw_text function, or within SDL/SDL_ttf. A memory leak detector will only be able to provide detailed information on leaks in your own code, not in third-party libraries. If it does not report any leaks in your code, I would not be terribly concerned about it unless the memory usage is substantial, in which case I would advise submitting a bug report.
jmcintyretech
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Thu Mar 28, 2013 1:02 pm

Re: Memory Leak with SDL Multiline Text

Post by jmcintyretech »

*******
Last edited by jmcintyretech on Fri Mar 18, 2016 10:06 am, edited 1 time in total.
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Memory Leak with SDL Multiline Text

Post by dandymcgee »

jmcintyretech wrote: 3. The leak is small and probably insignificant. I think at this point there is not much I can do to remedy it. Also, the leak only seems to occur when I switch between the main menu of the game and the level that draws the text. Unless somebody goes back and forth 100 times while playing the game it probably won't cause a serious leak.
I hope you're joking. You are joking right? If this is truly your mindset I sincerely hope you never develop software I have to use. This is like a car manufacturer saying, "Well, the airbags don't work but the rest of the car is fine. How many people ever actually use the airbags anyway?"
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
jmcintyretech
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Thu Mar 28, 2013 1:02 pm

Re: Memory Leak with SDL Multiline Text

Post by jmcintyretech »

********
Last edited by jmcintyretech on Fri Mar 18, 2016 10:07 am, edited 1 time in total.
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: Memory Leak with SDL Multiline Text

Post by eatcomics »

jmcintyretech wrote:Gotcha dandymcgee. Believe me I don't want to have that kind of mindset. I just meant that the bug seems to be in SDL and there is not much I can do to fix it on my own. At any rate I will TRY to fix it!

The last thing I want to do is write shitty, memory leaking software :nono:
Just so you know, most people I've talked to about the SDL TTF stuff have always just opted to create a png with all the characters and just blit the characters they need onto a surface. It seems to be the way to go, and that's what I do anymore. But yeah, don't just leave that leak in and keep using that function, it will only get worse.
Image
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Memory Leak with SDL Multiline Text

Post by dandymcgee »

eatcomics wrote:
jmcintyretech wrote:Gotcha dandymcgee. Believe me I don't want to have that kind of mindset. I just meant that the bug seems to be in SDL and there is not much I can do to fix it on my own. At any rate I will TRY to fix it!

The last thing I want to do is write shitty, memory leaking software :nono:
Just so you know, most people I've talked to about the SDL TTF stuff have always just opted to create a png with all the characters and just blit the characters they need onto a surface. It seems to be the way to go, and that's what I do anymore. But yeah, don't just leave that leak in and keep using that function, it will only get worse.
Yup, if the leak is party of a 3rd party library and you can't contact the developers to have it fixed, your solution is to stop using that library. Just because your include leaking code in your program doesn't excuse you from the fact that your software now leaks.

Have you given VLD a try? I would be curious to see what the output is.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Memory Leak with SDL Multiline Text

Post by Nokurn »

eatcomics wrote:Just so you know, most people I've talked to about the SDL TTF stuff have always just opted to create a png with all the characters and just blit the characters they need onto a surface. It seems to be the way to go, and that's what I do anymore. But yeah, don't just leave that leak in and keep using that function, it will only get worse.
My main complaint with this method is that, by using bitmap fonts, you lose scalability and virtually all of the kerning and metric information from FreeType. Writing an efficient font renderer using FreeType directly with OpenGL is trivial, gives good results, and can be altered to perform more advanced text drawing, such as extruded 3D glyphs, smooth scaling of glyph outlines, etc.

If OpenGL is out of the question and jmcintyretech wishes to continue using SDL_ttf, the most obvious optimization available to him is caching his text surfaces, I think. Something like this would work:
SDL_Surface* generate_text(TTF_Font* font, SDL_Color color, std::string text)
{
    std::size_t len = text.size();
    std::vector<SDL_Surface*> lines;
    int width = 0;
    int height = 0;
    for (std::size_t off = 0; off != std::string::npos;) {
        std::size_t next_off = text.find("\n");
        if (next_off != std::string::npos) {
            text[next_off] = '\0';
            ++next_off;
            if (next_off >= len)
                next_off = std::string::npos;
        }
        SDL_Surface* line = TTF_RenderText_Solid(font, &text[off], color);
        if (line) {
            if (line->w > width)
                width = line->w;
            height += line->h;
        }
        lines.push_back(line);
        off = next_off;
    }

    if (lines.empty())
        return SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, 24, 0, 0, 0, 0);

    SDL_Surface* surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0, 0, 0, 0);
    SDL_SetColorKey(surface, SDL_SRCCOLORKEY, 0);
    if (surface) {
        SDL_Rect dstrect = {0};
        std::vector<SDL_Surface*>::const_iterator it = lines.begin();
        std::vector<SDL_Surface*>::const_iterator end = lines.end();
        while (it != end) {
            SDL_Surface* line = *it;
            SDL_BlitSurface(line, NULL, surface, &dstrect);
            dstrect.y += line->h;
            SDL_FreeSurface(line); // clean up as we go
            ++it;
        }
    }

    return surface;
}

class main_menu {
public:
    main_menu()
    {
        static SDL_Color color = {0xFF, 0xFF, 0xFF};
        font = TTF_OpenFont("Arial.ttf", 32);
        text_surface = generate_text(font, color, "New Game\nLoad Game\nOptions\nQuit");
        text_off.x = (screen->w - text_surface->w) / 2;
        text_off.y = (screen->h - text_surface->h) / 2;
    }

    ~main_menu()
    {
        SDL_FreeSurface(text_surface);
        TTF_CloseFont(font);
    }

    void draw()
    {
        SDL_BlitSurface(text_surface, NULL, screen, &text_off);
    }

private:
    TTF_Font* font;
    SDL_Rect text_off;
    SDL_Surface* text_surface;
};
jmcintyretech
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Thu Mar 28, 2013 1:02 pm

Re: Memory Leak with SDL Multiline Text

Post by jmcintyretech »

********
Last edited by jmcintyretech on Fri Mar 18, 2016 10:07 am, edited 1 time in total.
jmcintyretech
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Thu Mar 28, 2013 1:02 pm

Re: Memory Leak with SDL Multiline Text

Post by jmcintyretech »

*******
Last edited by jmcintyretech on Fri Mar 18, 2016 10:07 am, edited 1 time in total.
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: Memory Leak with SDL Multiline Text

Post by eatcomics »

jmcintyretech wrote:

Code: Select all

No memory leaks detected.
Visual Leak Detector is now exiting.
The program '[1384] Terminal_Fantasy.exe: Native' has exited with code 0 (0x0).
VLD reports no problems with my code. Apparently the problem does lie within SDL_ttf. I will look into using OpenGL or using SDL in some other way.
There may be some other libraries for SDL that will let you use TTFs, but you'd have to look around. I agree with Nokurn, it is annoying that the most widely suggested TTF extension doesn't work, but usually people don't need all that TTF offers for an SDL project. But if someone would, I would say Nokurn's SDL solution is the way to go, if you can't find another library to use in conjunction with SDL.
Image
Post Reply