SDL2 Segmentation fault when trying to Poll Event - c++

I want to create a little program, which should draw some Math Functions.
At first a just wrote the code, that should create a little Window, that should just be visisble until I hit the X at the window.
#include <iostream>
#include <SDL2/SDL.h>
SDL_Window* window;
SDL_Renderer* renderer;
bool running = true;
bool init() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) return false;
window = SDL_CreateWindow("Visual Functions", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100, 200, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if(window == NULL) return false;
if(renderer == NULL) return false;
std::cout << "App and SDL init success" << std::endl;
return true;
}
void onEvent(SDL_Event* event) {
switch (event->type)
{
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
void loop() {
SDL_Event* event;
while(SDL_PollEvent(event)) onEvent(event);
}
void cleanUp() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
int main(int, char**) {
if(!init()) {
std::cout << "SDL or/and App init failed" << std::endl;
exit(-1);
}
while(running) loop();
cleanUp();
}
But the window pops so fast up and again down, that I couldn't even see it and in the command is at first App and SDL init success but then there stands Segmentation fault.
In a other code, which has the same Initialization and Loop code runs very well and everything is displayed displayed normally (at least for the SDL part).
I found out with some debug messages, that the loop comes not to the Event Function, but also not to the end of the Loop Function, so the problem is SDL_PollEvent(event), but what is the prolem and how to I fix it ?

You never create the SDL_Event struct that you are using:
void loop() {
SDL_Event* event;
while(SDL_PollEvent(event)) onEvent(event);
}
should be this
void loop() {
SDL_Event event;
while(SDL_PollEvent(&event)) onEvent(&event);
}

Related

SDL window sometimes fails to close on CTRL+C in terminal

Pressing CTRL+C while in the terminal sometimes fails to end the program:
int main(int argc, char *argv[]) {
DrawingWindow window = DrawingWindow(WIDTH, HEIGHT, false);
SDL_Event event;
while(true) {
if (window.pollForInputEvents(event)) handleEvent(event);
draw();
window.renderFrame();
}
}
}
bool DrawingWindow::pollForInputEvents(SDL_Event &event) {
if (SDL_PollEvent(&event)) {
if ((event.type == SDL_QUIT) || ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE))) {
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
printMessageAndQuit("Exiting", nullptr);
}
SDL_Event dummy;
// Clear the event queue by getting all available events
// This seems like bad practice (because it will skip some events) however preventing backlog is paramount !
while (SDL_PollEvent(&dummy));
return true;
}
return false;
}
void printMessageAndQuit(const std::string &message, const char *error) {
if (error == nullptr) {
std::cout << message << std::endl;
exit(0);
} else {
std::cout << message << " " << error << std::endl;
exit(1);
}
}
When CTRL+C succeeds (which is most of the time), it does print "Exiting".
I don't know what handleEvent supposed to do, and your code have braces mismatch so looks like it isn't even your actual code. As written, pollForInputEvents fetches one event, checks if it could be considered a quit condition, and then discards all other events in the queue regardless. If event you're looking for happens to be non-first (e.g. as first event you may have keydown of 'ctrl' or mouse move, or window close event, ...), then it never gets processed. handleEvent has the same problem - it gets only first event in frame.
Generally speaking, event processing have to happen in a fast non-blocking loop, which handles events faster than new events are getting in. Processing only one event per frame is a not fast enough, and there is absolutely no reason to process only one event. Events gets accumulated in a queue, you process all events, draw your image frame (potentially slow), present on screen (potentially blocking on vsync), then repeat.
It looks counterintuitive that your event processing is split into two functions.
As I don't see the rest of your code, with "minimal" changes it should be something like:
#include <SDL2/SDL.h>
#include <iostream>
#define WIDTH 640
#define HEIGHT 480
static void handleEvent(SDL_Event &event) {}
static void draw(SDL_Renderer *renderer) {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
}
class DrawingWindow {
public:
DrawingWindow(int width, int height, bool fs) {
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
width, height, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
}
bool pollForInputEvents(SDL_Event &event);
void renderFrame() {
SDL_RenderPresent(renderer);
}
SDL_Window *window;
SDL_Renderer *renderer;
};
void printMessageAndQuit(const std::string &message, const char *error) {
if (error == nullptr) {
std::cout << message << std::endl;
exit(0);
} else {
std::cout << message << " " << error << std::endl;
exit(1);
}
}
bool DrawingWindow::pollForInputEvents(SDL_Event &event) {
if (SDL_PollEvent(&event)) {
if ((event.type == SDL_QUIT) || ((event.type == SDL_KEYDOWN) && (event.key.keysym.sym == SDLK_ESCAPE))) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
printMessageAndQuit("Exiting", nullptr);
}
return true;
}
return false;
}
int main(int argc, char *argv[]) {
DrawingWindow window = DrawingWindow(WIDTH, HEIGHT, false);
SDL_Event event;
while(true) {
while(window.pollForInputEvents(event)) handleEvent(event);
draw(window.renderer);
window.renderFrame();
}
}

How to fix SDL2 'Assertion failure at SDL_RenderClear_REAL' in C++?

I'm learning the basics of creating a window using SDL2 by following a tutorial. The code works just fine, and even compiles correctly, however on runtime it gives the error message 'Assertion failure at SDL_RenderClear_REAL'.
I've tried reinstalling SDL2, as well as moving it to the user library folder on my mac, but neither of these fixed the issue
main.cpp
#include "game.hpp"
Game *game = nullptr;
int main() {
game = new Game();
game->init("GUI", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, false);
while (game->running()) {
game->handleEvents();
game->update();
game->render();
}
game->clean();
return 0;
}
game.cpp
#include "game.hpp"
Game::Game(){}
Game::~Game(){}
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) {
int flags = 0;
if (fullscreen == true) {
flags = SDL_WINDOW_FULLSCREEN;
}
if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "Sub-systems initialized\n";
window = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if (window) {
std::cout << "Window created.\n";
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
std::cout << "Renderer created\n";
}
isRunning = true;
} else {
isRunning = false;
}
}
void Game::handleEvents() {
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
default:
break;
}
}
void Game::update() {
cnt++;
std::cout << cnt << "\n";
}
void Game::render() {
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void Game::clean() {
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
std::cout << "Game cleaned\n";
}
game.hpp
#ifndef game_hpp
#define game_hpp
#include "SDL2/SDL.h"
#include <iostream>
class Game {
public:
Game();
~Game();
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void handleEvents();
void update();
void render();
void clean();
bool running() { return isRunning; }
private:
int cnt = 0;
bool isRunning;
SDL_Window *window;
SDL_Renderer *renderer;
};
#endif
After narrowing down the code, it seems that the issue is limited to SL_RenderClear. Here's the exact message it produces in the console:
2019-08-20 15:26:15.508900-0500 GUI[26436:7287503] WARN:
Assertion failure at SDL_RenderClear_REAL (/Users/valve/release/SDL/SDL2-2.0.10-source/src/render/SDL_render.c:2235), triggered 1 time:
'renderer && renderer->magic == &renderer_magic'
Program ended with exit code: 42
How can I fix this issue?
EDIT: Added full code to help identify the problem.
A basic "hello world" of creating a window and clearing the color on the screen for SDL requires a few boilerplate initialization steps
Initialize SDL
Create a SDL_Window
Create a SDL_Renderer
After which you can do
SDL_RenderClear and use SDL_RenderDrawColor to set a custom color to make it more obvious that it is properly clearing the Renderer.
Without error checking this would look something like:
SDL_Init(flags);
SDL_Window* window = SDL_CreateWindow("window title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, more_flags);
SDL_SetRenderDrawColor(renderer, red, green, blue, alpha);
SDL_RenderClear(renderer);
Also remember to call SDL_Delay(ms) if you want the program to not immediately close before you get a chance to see the window.

c++ with SDL not running

i've installed SDL to develop a program, and while on the test phase for this lib, the compiled code does not execute, and i mean it won't even open the cmd box. The weird thing is, it occasionally executes.
I'm using Eclipse Hellios with minGW32 and i686-w64-mingw32 on windows10.
My test code is:
#include <iostream>
#include <Windows.h>
#include <SDL2/SDL.h>
int main(int, char**)
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) return 1;
SDL_Window *window = SDL_CreateWindow("", 300, 100, 1024, 800, SDL_WINDOW_OPENGL);
if (window == NULL)
{
std::cout << "SDL init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface *background = SDL_LoadBMP("Resources/Lilothyn.bmp");
if (background == NULL)
{
SDL_ShowSimpleMessageBox(0, "Background init error", SDL_GetError(), window);
return 1;
}
if (renderer == NULL)
{
SDL_ShowSimpleMessageBox(0, "Renderer init error", SDL_GetError(), window);
}
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, background);
if (texture == NULL)
{
SDL_ShowSimpleMessageBox(0, "Texture init error", SDL_GetError(), window);
}
SDL_RenderPresent(renderer);
SDL_Event event;
bool running = true;
while(running)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
running = false;
SDL_DestroyTexture(texture);
SDL_FreeSurface(background);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
break;
default: break;
}
}
return 0;
}
the odd thing is, i previously had "SDL_LoadBMP("Resources/TommyBMP.bmp");" and it executed properly. Changing a string shouldn't make the program stop working, both files are at the Debug/Resources folder so it can't be a case of not finding them...
note: further testing shows that a simple "hello world" has the same issue, so the problem will likely not be from SDL.
"help me obi wan, you're my only hope".

SDL window not showing?

I have this simple code for SDL.
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
using namespace std;
int main(int argc, char * argv[]){
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
return 1;
}
SDL_Window * win = SDL_CreateWindow("Window", 0, 0, 1920, 1080, SDL_WINDOW_FULLSCREEN_DESKTOP);
if(win == nullptr){
return 1;
}
SDL_Quit();
return 0;
}
None of this shows a window, I have error checked everything. It was working previously, but now it just opens and closes. I'm running on Xcode, if that helps.
Like the others state, your program terminates immediately so the window should "flash" momentarily. You can have the window appear for a few seconds by using SDL_Delay:
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Delay(2000);
SDL_DestroyWindow(win);
SDL_Quit();
And remember to call SDL_DestroyWindow.
A while(true) {} loop will just cause your program to freeze. You probably want something like the following so that it listens for events, and you can close the window at your leisure.
SDL_Event e;
bool quit = false;
while (!quit){
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT){
quit = true;
}
if (e.type == SDL_KEYDOWN){
quit = true;
}
if (e.type == SDL_MOUSEBUTTONDOWN){
quit = true;
}
}
}

SDL not responding after running for a few seconds on linux

I was following the SDL Game development book and I cant even get the first file to work right. Upon the application starting it renders the window and then after a few seconds Linux says the game is not responding and ask me to force quit. This repeats every few seconds if I click wait. One thing I have noticed is that SDL_PollEvent never returns true.I am not sure why things are not working. Here is my code.
Main.cpp
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include "Game.h"
// our Game object
Game* g_game = 0;
int main(int argc, char* argv[]) {
g_game = new Game();
g_game->init("Chapter 1", 100, 100, 640, 480, 0);
while(g_game->running()) {
g_game->handleEvents();
//g_game->update();
g_game->render();
}
g_game->clean();
return 0;
}
Game.h
#ifndef __Game__
#define __Game__
#if !WINDOWS
#include <SDL2/SDL.h>
#else
#include <SDL.h>
#endif
class Game {
public:
Game() {}
~Game() {}
// simply set the running variable to true
bool init(const char* title, int xpos, int ypos, int width, int
height, bool fullscreen);
void render();
void update();
void handleEvents();
void clean();
// a function to access the private running variable
bool running() {
return m_bRunning;
}
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
bool m_bRunning;
};
#endif /* defined(__Game__) */
Game.cpp
#include "Game.h"
#include <iostream>
bool Game::init(const char* title, int xpos, int ypos, int width,
int height, bool fullscreen) {
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "SDL init success\n";
// init the window
int flags = 0;
if(fullscreen) {
flags = SDL_WINDOW_FULLSCREEN;
}
m_pWindow = SDL_CreateWindow(title, xpos, ypos,
width, height, flags);
if(m_pWindow != 0) { // window init success
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) { // renderer init success
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer,
255,0,255,255);
} else {
std::cout << "renderer init fail\n";
return false; // renderer init fail
}
} else {
std::cout << "window init fail\n";
return false; // window init fail
}
} else {
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
void Game::render() {
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean() {
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::handleEvents() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
std::cout << "Checking Events";
switch(event.type) {
case SDL_QUIT:
std::cout << "Quiting";
m_bRunning = false;
break;
default:
break;
}
}
}
Edit:
so I made a minamal version of the code and now i get a new error. The error says "Segmentation Fault (core dumped)". Based on running it to a specific line in debug the error seems to appear at the line that says "SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);" I am not sure what the error is though
Here is the minial code:
#ifdef __cplusplus
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char** argv) {
if(SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if(win == NULL) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(ren == NULL) {
SDL_DestroyWindow(win);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
std::string imagePath = "cb.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if(bmp == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
if(tex == NULL) {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_FreeSurface(bmp);
SDL_Event e;
bool quit = false;
while(!quit) {
while(SDL_PollEvent(&e)) {
//If user closes the window
if(e.type == SDL_QUIT) {
quit = true;
}
//If user presses any key
if(e.type == SDL_KEYDOWN) {
quit = true;
}
//If user clicks the mouse
if(e.type == SDL_MOUSEBUTTONDOWN) {
quit = true;
}
}
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
I have compiled and run your minimal code successfully under Linux with SDL 2.0.4. I used a simple image as "cb.bmp".
Try the following :
compile like this : g++ -Wall -ggdb $(sdl2-config --cflags) -o program main.cpp -lSDL2
gdb ./program, then type 'run'
when it crashes, type 'bt' (for backtrace)
copy the output here
My guess is : either the "bmp" file format is not supported or the rendering driver is not supported. try to use :
SDL_CreateRenderer(win, -1, 0);