Jump to content

View more

Image of the Day

Boxes as reward for our ranking mode. ヾ(☆▽☆)
#indiedev #gamedev #gameart #screenshotsaturday https://t.co/ALF1InmM7K
IOTD | Top Screenshots

The latest, straight to your Inbox.

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


Sign up now

SDL_TTF crashes c++ program?

4: Adsense
  • You cannot reply to this topic
15 replies to this topic

#1 starfruit64   Members   

106
Like
0Likes
Like

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. 



#2 vstrakh   Members   

2389
Like
2Likes
Like

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



#3 Fonzki   Members   

120
Like
0Likes
Like

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.



#4 starfruit64   Members   

106
Like
0Likes
Like

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).



#5 vstrakh   Members   

2389
Like
1Likes
Like

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.



#6 starfruit64   Members   

106
Like
0Likes
Like

Posted 20 April 2017 - 06:47 PM

Ignore this


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


#7 starfruit64   Members   

106
Like
0Likes
Like

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?



#8 vstrakh   Members   

2389
Like
0Likes
Like

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.



#9 starfruit64   Members   

106
Like
0Likes
Like

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.


#10 vstrakh   Members   

2389
Like
1Likes
Like

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.



#11 rip-off   Moderators   

10889
Like
1Likes
Like

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).

#12 starfruit64   Members   

106
Like
0Likes
Like

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?



#13 vstrakh   Members   

2389
Like
0Likes
Like

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.



#14 starfruit64   Members   

106
Like
0Likes
Like

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?



#15 Lactose   GDNet+   

10818
Like
1Likes
Like

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.

#16 rip-off   Moderators   

10889
Like
1Likes
Like

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.