View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# SDL_TTF crashes c++ program?

15 replies to this topic

### #1starfruit64  Members

Posted 16 April 2017 - 12:41 PM

Hello, this is my first time using this forum so if im doing something wrong please tell me. I am very new to programming and I have been playing around with SDL for a while. I am now trying to display text on the screen using SDL_ttf. Using an internet tutorial, I have made a "Display text" function in my Screen class. Before I added the code my program ran fine. Now it crashes, even if my main function is blank. My ide shows me no error. When I try to run the program in windows cmd i get the error: "The program can't start because SDL2_ttf.dll is missing from your computer. Try reinstalling the program to fix this problem."  This is strange because I can see "libSDL2_ttf.dll.a" in my SDL2 folder.

### #2vstrakh  Members

Posted 16 April 2017 - 01:12 PM

I can see "libSDL2_ttf.dll.a" in my SDL2 folder.

'*.dll.a' is not a dynamic '.dll' library.  If library ends with .a - then this library is linked statically. In your case it's .dll.a, means it's import library, it tells your compiler's linker to search for actual function in some .dll file, linked later dynamically, by system. You still need libSDL2_ttf.dll

### #3Fonzki  Members

Posted 16 April 2017 - 03:02 PM

If you're using SDL & C++ you may find the Lazy Foo' Tutorial on extensions helpful

He's specifically uses SDL_TTF in this lesson

More tutorials by him are here.

### #4starfruit64  Members

Posted 16 April 2017 - 03:09 PM

I can see "libSDL2_ttf.dll.a" in my SDL2 folder.

'*.dll.a' is not a dynamic '.dll' library.  If library ends with .a - then this library is linked statically. In your case it's .dll.a, means it's import library, it tells your compiler's linker to search for actual function in some .dll file, linked later dynamically, by system. You still need libSDL2_ttf.dll

This fixed the  "The program can't start because SDL2_ttf.dll is missing from your computer. Try reinstalling the program to fix this problem." but now I get a "The application was unable to start correctly (0xc000007b). Click OK to close the application." error, followed by a crash. Again, my main code is blank, and threes a single class with a header and .cpp (That I haven't even included).

### #5vstrakh  Members

Posted 17 April 2017 - 12:52 AM

now I get a "The application was unable to start correctly (0xc000007b).

Check that dll you've copied was compiled for the same runtime as your main project. If something won't match (32-bit dll in 64-bit program, debugging/multithreading settings, etc), then program will fail to start.

### #6starfruit64  Members

Posted 20 April 2017 - 06:47 PM

Ignore this

Edited by starfruit64, 20 April 2017 - 06:54 PM.

### #7starfruit64  Members

Posted 20 April 2017 - 06:57 PM

now I get a "The application was unable to start correctly (0xc000007b).

Check that dll you've copied was compiled for the same runtime as your main project. If something won't match (32-bit dll in 64-bit program, debugging/multithreading settings, etc), then program will fail to start.

This fixes the "The application was unable to start correctly (0xc000007b)." error. Now i just get a crash. Anytime i use something related to SDL_TTF i get a crash, with no error in Eclipse. Any ideas?

### #8vstrakh  Members

Posted 21 April 2017 - 01:28 AM

Anytime i use something related to SDL_TTF i get a crash

Now it might be anything, since it's your actions. You'll have to show minimal crashing example, which we can build and test. Maybe you didn't initialize library properly, or misused it in some other way.

### #9starfruit64  Members

Posted 21 April 2017 - 03:47 PM

Anytime i use something related to SDL_TTF i get a crash

Now it might be anything, since it's your actions. You'll have to show minimal crashing example, which we can build and test. Maybe you didn't initialize library properly, or misused it in some other way.

Alright here is the minimal it takes to crash the program. I tested each step as i added code, and it only crashed once i got to this:

#include <iostream>
#include <fstream>
#include <SDL.h>
#include "SDL_ttf.h"
#include "Input.h"
#include "Screen.h"

const static int WIDTH = 800;
const static int HIGHT = 600;

using namespace std;
int main(int argc, char* argv[]) {

if (SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_Quit();
}
if (TTF_Init() == -1) {
SDL_Quit();

}

SDL_Window *window = SDL_CreateWindow("test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, WIDTH, HIGHT, SDL_WINDOW_SHOWN);
if (window == NULL) {
return false;
}

SDL_Renderer *renderer = SDL_CreateRenderer(window, -1,
SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
return false;
SDL_DestroyWindow(window);
SDL_Quit();
}

SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STATIC, WIDTH, HIGHT);
if (texture == NULL) {
return false;
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
}

TTF_Font* font = TTF_OpenFont("Sans.ttf", 24);

SDL_Color color = {255, 255, 255};

SDL_Surface* surfaceMessage = TTF_RenderText_Solid(font, "Hello World!", color);

SDL_Texture* message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
SDL_Rect message_rect;
message_rect.x = 0;
message_rect.y = 0;
message_rect.w = 100;
message_rect.h = 100;

SDL_RenderCopy(renderer, message, NULL, &message_rect);

SDL_Quit();
TTF_Quit();
return 0;
}


Edited by starfruit64, 21 April 2017 - 03:48 PM.

### #10vstrakh  Members

Posted 22 April 2017 - 01:23 AM

This code would crash if no "Sans.ttf" file could be found in app's current working directory. It doesn't crash otherwise for me. Check what's result from TTF_OpenFont(), is it null or a valid pointer.

### #11rip-off  Moderators

Posted 22 April 2017 - 03:28 AM

Also when you detect an error (e.g. window == null), try printing SDL_GetError() to the console before quitting. If you get an error with SDL_TTF, use TTF_GetError().

If you "return false" from main(), technically you are reporting your program ran successfully. Main returns an "Int", not a boolean (although a boolean will convert to an Int). So when an error occurs, use " return 1" instead, or you can use EXIT_FAILURE (http://en.cppreference.com/w/cpp/utility/program/EXIT_status).

### #12starfruit64  Members

Posted 22 April 2017 - 12:08 PM

This code would crash if no "Sans.ttf" file could be found in app's current working directory. It doesn't crash otherwise for me. Check what's result from TTF_OpenFont(), is it null or a valid pointer.

How can I check this? I think you are right in that i dont have Sans.ttf in the current working directory, but how can i find out what that directory is?

### #13vstrakh  Members

Posted 22 April 2017 - 02:19 PM

Working directory could be anything, and probably you don't need to know that at all.

What you need to know is where .exe file located, so resources could be read by the path relative to .exe location. See SDL_GetBasePath() function: https://wiki.libsdl.org/SDL_GetBasePath

Place your assets near exe file, maybe in subdirectories. Then open it by concatenated name - base path and asset file name.

### #14starfruit64  Members

Posted Yesterday, 10:31 AM

Working directory could be anything, and probably you don't need to know that at all.

What you need to know is where .exe file located, so resources could be read by the path relative to .exe location. See SDL_GetBasePath() function: https://wiki.libsdl.org/SDL_GetBasePath

Place your assets near exe file, maybe in subdirectories. Then open it by concatenated name - base path and asset file name.

Alright you and everyone else has been super helpful. This fixed the crash but now when I run the program and update the screen, the text isn't there. My code is this:


#include <iostream>
#include <fstream>
#include <SDL.h>
#include "SDL_ttf.h"
#include "Input.h"
#include "Screen.h"

using namespace std;
Screen screen;
Input input;
SDL_Renderer *renderer;
int main(int argc, char* argv[]) {
screen.init();

screen.test_text();

screen.update();

while (true) {
string event = input.check_event();
if(event == "1"){
break;
}
}

TTF_Quit();
SDL_Quit();
return 0;
}



screen.init(); does this:

bool Screen::init() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
return false;
}
if(TTF_Init()==-1) {
printf("TTF_Init: %s\n", TTF_GetError());
exit(2);
}

window = SDL_CreateWindow("Particle Simulation", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, WIDTH, HIGHT, SDL_WINDOW_SHOWN);
if (window == NULL) {
return false;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
return false;
SDL_DestroyWindow(window);
SDL_Quit();
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STATIC, WIDTH, HIGHT);
if (texture == NULL) {
return false;
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
}
buffer = new Uint32[WIDTH * HIGHT];

return true;
} 

screen.test_text(); does this:

void Screen::test_text(){
TTF_Font* font = TTF_OpenFont("C:\\Users\\KP7\\Desktop\\C++2\\Hero\\Debug\\block.ttf", 24);

SDL_Color color = {255, 255, 255};

SDL_Surface* surfaceMessage = TTF_RenderText_Solid(font, "Hello World!", color);

SDL_Texture* message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);

SDL_Rect message_rect;
message_rect.x = 0;
message_rect.y = 0;
message_rect.w = 100;
message_rect.h = 100;

SDL_RenderCopy(renderer, message, NULL, &message_rect);
} 

and screen.update(); does this:

void Screen::update() {
SDL_UpdateTexture(texture, NULL, buffer, WIDTH * sizeof(Uint32));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
} 

This just displays a black screen for me. Does anyone know why?

### #15Lactose  GDNet+

Posted Yesterday, 11:57 AM

Screen::update does a SDL_RenderClear, which essentially deletes everything you tried to render in test_text.

Additionally, you have a SDL_RenderCopy there as well, which I assume would overwrite anything you have in text_text.

You should reshuffle your code a bit:

1. Load everything you need (fonts, etc.).

2. While loop, lasting until some condition:

3a. Clear.

3b. Draw stuff (background, then text). Could also be just text, to make things slightly less complicated.

3c. Present.

Hello to all my stalkers.

### #16rip-off  Moderators

Posted Today, 07:23 AM

You have some error handling, but there are still a few issues. You haven't handled every error, e.g. Screen::test_text contains no error handling if the font fails to open, or the text rendering fails, or converting the surface to a texture fails.

The error handling you do have is inconsistent, you don't cleanup all the resources. In fact, you have some unreachable code, once you execute "return <some value>", no other statements in that function will be executed.

Full error handling in Screen::init would look something like this:

bool Screen::init() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
return false;
}
std::atexit(&SDL_QUIT);

if (TTF_Init() < 0) {
printf("TTF_Init: %s\n", TTF_GetError());
return false;
}
std::atexit(&TTF_Quit);

window = SDL_CreateWindow("Particle Simulation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HIGHT, SDL_WINDOW_SHOWN);
if (window == NULL) {
printf("SDL_CreateWindow failed: %s\n", SDL_GetError());
return false;
}

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
printf("SDL_CreateRenderer failed: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
return false;
}

texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, WIDTH, HIGHT);
if (texture == NULL) {
printf("SDL_CreateTexture failed: %s\n", SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return false;
}

buffer = new Uint32[WIDTH * HIGHT];
return true;
}



(This isn't 100% complete as technically the new statement could throw an exception, but this is very unlikely). Note the use of std::atexit(...) to avoid having to tear down SDL and TTF for every error case. I'd probably move these to the start of main() or a separate init() routine.

You can simplify the error handling by creating many simple classes that each manage a single resource - the chain of cleanup operations can be automatically managed due to the object's destructors being called.