SDL shared_ptr problems

Nibbie
Posts: 3
Joined: 2011.03
Post: #1
Hi everyone!

I'm having some trouble with a game I'm developing.
I'm using the SDL framework and everything has been going on smoothly until now! I store all pointers in shared_ptr to eliminate possible memory leaks and since I use shared_ptr I can specify a deleter function which is needed in this case.

e.g
SDL_Surface* surface;

. Load
. Image
. Into
. Surface

shared_ptr<SDL_Surface> pointer(surface, SDL_FreeSurface);

This works extremly good for me but I have a problem with my font class. I have a class that loads fonts and store them in a vector. Then another function is used to generate text with one of the fonts in the vector by taking a index as a parameter and using the font at that index within the vector to generate the text.

Here is my class:

Code:
#include "FontHandler.h"

// Must declare it here as well, otherwise it won't be initialized and we'll get an
// unresolved external symbol when we try to use the vector
std::vector<shared_ptr<TTF_Font> > FontHandler::fontVector;

bool FontHandler::LoadFont(const char* fileName, int fontSize)
{
    TTF_Font* tmpfont = TTF_OpenFont(fileName, fontSize);

    if (tmpfont == NULL)
        return false;

    fontVector.push_back(shared_ptr<TTF_Font>(tmpfont, TTF_CloseFont));

    return true;
}

shared_ptr<SDL_Surface> FontHandler::GenerateText(fontIndex index, unsigned char r, unsigned char g, unsigned char b, unsigned char a, const char* text)
{
    if (index < 0 || index >= fontVector.size())
        return shared_ptr<SDL_Surface>();

    SDL_Color fontColor = {r, g, b, a};

    SDL_Surface* returnText = TTF_RenderText_Solid(fontVector[index].get(), text, fontColor);

    return shared_ptr<SDL_Surface>(returnText, SDL_FreeSurface);
}

This works great except one small problem. If I run the game with the debugger it gives an exception when I close the game (when all the automatic resource cleaning because all the shared_ptr's take place).
It is the shared_ptr's that holds TTF_Font* that makes it crash, eventhough I handle SDL_Surface* and Mix_Chunk* the exact same way.

The exception is: "Unhandled exception at 0x6fbc2ec4 in Frogger.exe: 0xC0000005: Access violation reading location 0xfeeefef6."

and the debugger stops at:

Code:
virtual void dispose() // nothrow
    {
        del( ptr );
    }

in the file sp_counted_impl.hpp

The call stack is: > Frogger.exe!boost::detail::sp_counted_impl_pd<_TTF_Font *,void (__cdecl*)(_TTF_Font *)>::dispose() Line 144 + 0x9 byt

so I know it is the shared_ptr's that holds TTF_Font* that is the problem. It is wierd though, since I specify TTF_CloseFont as the "deleter" function for them, which I belive is correct. What's even more strange is that I don't have the same problems with, for an example, my shared_ptr<SDL_Surface>. And like I said, the exception only comes when I run the game with the debugger, otherwise it exits correctly...

I've found a way around this with implementing the following function:

Code:
void FontHandler::ResetFonts()
{
    for (fontIndex i = 0; i < fontVector.size(); i++)
        fontVector[i].reset();
}

If I call that one before TTF_Quit(); and SDL_Quit(); the exception never comes... But it annoys me a lot since I shouldn't need to do that, and I don't need to do that with other shared_ptr's.. Is there something special with TTF_CloseFont that I am missing?

Very greatfull for any thoughs on this matter!

Best regards
Björn
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
1) valgrind. You've got a lot of information here which suggests you know pretty much what you're doing, you just need better tools to diagnose it. valgrind is your better tool.

2) In general, you don't want to do *anything* when the user quits. Let the OS clean up the resources, it'll do it as well as you can, faster than you can, and without the risk of crashes Rasp C++ static destructors are evil in this sense, since they'll run even if you call exit(). If you must have globals, make them pointers.
Quote this message in a reply
Nibbie
Posts: 3
Joined: 2011.03
Post: #3
Thx for your reply.

Do you know any good alternatives to valgrind that works for Windows (and doesn't costs tons of money Grin).
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #4
No, but you're using SDL, so you shouldn't have any trouble porting your game to a decent OS.
Quote this message in a reply
Member
Posts: 27
Joined: 2009.07
Post: #5
Are you using shared_ptr from the Boost libraries? If so, I believe they've got a number of issues when being combined with STL structors like list<> and vector<>.

Goodbye.
Quote this message in a reply
Nibbie
Posts: 3
Joined: 2011.03
Post: #6
Yes I'm using boost::shared_ptr not std::tr1::shared_ptr.

However, it works perfectly in all other cases except for with the TTF_Font... And I had the same problem before I started to store them in a vector. It seems to me that it is something that TTF_CloseFont does that makes things go bad. Hmm rather it seems I'm doing something wrong with TTF_CloseFont Smile But as I said, if I call .reset() on the shared_ptr before the game ends, everything works perfectly. So I have a semi-solution. The thing that bothers me is that it works without .reset() on all the other kinds of shared_ptr<> I'm using in the game.

Oh, and isn't it auto_ptr that doesn't worlk with STL containers because of its weird copy-behavior? (Change ownership istead of copy)

OneSadCookie:

Hehe well that is true. I've already tried the game on a macbook and it compiles without any problems. But I don't really have the time to install Linux on my own computer at the moment. But I will most definitely install a linux dist. and check out valgrind whenever I get enough time for it Smile
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #7
(Mar 29, 2011 10:45 AM)Minalien Wrote:  Are you using shared_ptr from the Boost libraries? If so, I believe they've got a number of issues when being combined with STL structors like list<> and vector<>.

You're thinking of std::auto_ptr<> -- never, ever, use auto_ptr with collections. That being said, boost::shared_ptr<> works beautifully.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  boost dynamic_pointer_cast, shared_ptr not working as expected JeroMiya 2 7,357 Nov 24, 2008 01:29 AM
Last Post: masumbuet