2

I'm trying to make a game in C using SDL_ttf to display the score every time the diplay is refreshed. The code looks like :

SDL_Surface *score = NULL;

TTF_Font *font;
SDL_Color color = { 255, 255, 255 };
font = TTF_OpenFont( "/home/sophie/Bureau/snake/data/ubuntu.ttf", 28 );
if (font == NULL) {
    printf("%s\n", TTF_GetError()); 
}

score = TTF_RenderText_Solid( font, "score to display", color );

SDL_BlitSurface( score, NULL, screen, NULL );
SDL_Flip(screen);

When I launch the game, everything works properly, but after a while the game crashes and I get the following error :

Couldn't open /home/sophie/Bureau/snake/data/ubuntu.ttf
libgcc_s.so.1 must be installed for pthread_cancel to work
Abandon (core dumped)

I tried different fonts but I still have this problem. Then I used a counter in the main loop of the game and found that the game always crashes after the 1008th time, regardless of the speed I wanted it to work at (in snake everything goes faster when you score points).

I don't know where does the problem comes from, nor what exactly does the error message mean.

Please tell me if you have any ideas, or if my question is poorly formulated. I looked on several forums and found nothing corresponding to my case, I could use any help now !

Thanks in advance

Zeenoth
  • 23
  • 2
  • From your description, I get the impression you are doing the `TTF_OpenFont` inside your main game loop. Is that correct? – Jongware Feb 07 '14 at 22:29
  • No, actually this segment is inside a function called by another function that is in the main loop. I thought it would be too complicated to give the real code since the error message indicates the error is here... Was I wrong ? – Zeenoth Feb 07 '14 at 22:40

1 Answers1

1

It looks like you're repeatedly opening the font every time you go through this function:

font = TTF_OpenFont( "/home/sophie/Bureau/snake/data/ubuntu.ttf", 28 );

While it may not be in the main game loop as Jongware suspected, you mentioned that after 1008 executions through this code path, the code crashes.

What is happening is that some resource is being leaked. Either the resource needs to be released by calling TTF_CloseFont() or (more efficient) hold onto the handle after the first time you open it and re-use it each time. Use a static declaration for the font and initialize to NULL:

static TTF_Font *font = NULL;

Then, if it hasn't been opened yet, open it:

if (!font) {
    font = TTF_OpenFont( "/home/sophie/Bureau/snake/data/ubuntu.ttf", 28 );
}

This will initialize font the first time while subsequent iterations over the code will not unnecessarily re-do the process and leak the resource.

You mentioned that the code crashes after 1008 times through this function. That's pretty close to 1024. As memory serves, Linux has a limit of 1024 file handles per process (this is probably tunable in the kernel but I have run into this limitation in debugging resource leaks before). There are probably 16 other file handles open by your process and then 1 process being leaked by each invocation of TTF_OpenFont. Once you go above 1024, boom.

You can check the number of open file handles of a particular process (<pid>) by inspecting the number of file descriptors in /proc/<pid>/fd/.

Multimedia Mike
  • 12,660
  • 5
  • 46
  • 62
  • 1
    I had never heard of static declarations before, I tried what you said. It seems that the problem was exactly what you said, and now my program is running perfectly. Thank you very much ! – Zeenoth Feb 08 '14 at 14:23
  • 1
    Be sure to read up on static declarations a bit more. 'static' means several different things depending on context. Also, interviewers like using these different static use contexts for interview questions for C-related jobs, in my experience. :-) – Multimedia Mike Feb 08 '14 at 16:48
  • 1
    OK I will read a bit more about it ^^ Also, I have been looking into /proc//fd/ and using ll to see what was inside and found out that there were two sockets. I've done nothing related to networks, how did these two elements come up ? – Zeenoth Feb 08 '14 at 19:03
  • 1
    There are a lot of different reasons to use sockets. E.g., connecting to a MySQL server, even hosted on the same box, will use a socket. And you might not be explicitly opening any sockets, but you're using various libraries which might be opening sockets. They might be doing so just to communicate with services on the system (perhaps the audio output is implemented as a service). – Multimedia Mike Feb 08 '14 at 20:42