this is my first experience,so don't be picky.
It's SIGSEGV problem, and it appears only in class linking.
The problem within "SDL_surface *ScreenSurface" pointer.
Here goes the code...
Screen header
class screen
{
public:
screen();
SDLclass_Window *MainWindow=NULL;
SDL_Surface *ScreenSurface=NULL; //this is the problem pointer to the struct that cause error
//Those pointer are't NULL, see below
virtual ~screen();
protected:
private:
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 726;
bool init();
};
Screen code
screen::screen()
{
if(!init())
{
std::cout<<"ERROR at INIT";
SDL_Delay( 4000 );
}
else
{
bool quit=0;
SDL_Event e;
while (!quit)
{
SDL_UpdateWindowSurface(MainWindow);
//Looking for events
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}
}
}
this->~screen();
}
bool screen::init() //Initialization
{
bool succses=1;
if (SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
std::cout<< "SDL could not initialize! SDL_Error:"<< SDL_GetError()<<std::endl;
succses=0;
return succses;
}
MainWindow= SDL_CreateWindow( "Arachy: WIP Version", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); //Setting parameters to SDL_window
if (MainWindow==NULL)
{
std::cout<<"can't create window"<<SDL_GetError()<<std::endl;
succses=0;
return succses;
}
else
{
//Get window surface
ScreenSurface = SDL_GetWindowSurface( MainWindow );// telling ScreenSurface that it our main screen surface
}
return succses;
}
screen::~screen()
{
SDL_Quit();
}
Activity header
(another class that uses SDL_Surface which defined above in class Screen)
class activity
{
public:
activity();
virtual ~activity();
protected:
private:
screen mainScreen;
void load();
};
Activity code (I'm trying to modify SDL_Surface with SDL_FillRect() after that i got SIGSEGV signal during debug
activity::activity()
{
SDL_FillRect(mainScreen.ScreenSurface,NULL,SDL_MapRGB(mainScreen.ScreenSurface->format,255,000000,255));
}
Please , help me to find out...
Thank you
The problem is twofold:
A) It's likely that the destructor of screen is called twice, causing SDL_DestroyWindow() and SDL_FreeSurface() to be called on invalid, non-NULL pointers.
If you absolutely, positively want to call your destructor twice, you should at least reset these pointers to NULL after destroying the objects they point to.
But in most cases you should simply, you know, not explicitly call the destructor...
B) As set now, activity's constructor body will never be called until the main event loop is over.
Related
I'm aware that there are several similar questions to this one already, but I've read through them and none of them seem to cover my specific problem...
I'm trying to dereference a public pointer from a struct, but it's throwing a SIGSEV Segmentation fault, even though the pointer does point to a value
It prints 1 & 2 but does not get any further. If I change it to reference the pointer rather than the value, the error moves to wherever I reference the value, so I know the issue is with dereferencing, not the rest of the line.
If you need to see any more of my code in order to find the issue, just ask. I just didn't want to make you trawl through hundreds of lines unnecesarily...
#include <vector>
#include "Entities.cpp"
struct Chunk {
public:
std::vector<BaseEntity>* environment; // this is what I'm trying to access
Chunk() {
environment = new std::vector<BaseEntity>(1); // this is where init
environment->push_back(Grass()); // adding something to it works fine
}
~Chunk() {
delete(environment);
}
};
class World {
public:
Chunk* loaded[3][3];
World() {
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++) {
loaded[x][y] = new Chunk();
}
}
~World() {
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++) {
delete(loaded[x][y]);
}
}
};
And here's the code that accesses it (in another class & file)
void render(SDL_Renderer* gRenderer, Atlas* atlas, World* world, int SCREEN_WIDTH, int SCREEN_HEIGHT) {
printf("1");
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++) {
printf("2");
std::vector<BaseEntity> env =
*(world->loaded[x][y]->environment); // here is where the error occurs
printf("3");
printf('0' + env.size() + "");
printf("a");
for (const auto& a : env) {
printf("b");
drawTexture(gRenderer, atlas, a.atlasID,
SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
}
printf("4");
}
printf("5");
}
This is the code that calls it:
int main(int argv, char** args) {
SDL_Init( SDL_INIT_VIDEO );
//The window we'll be rendering to
SDL_Window* gWindow = SDL_CreateWindow(
title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if (gWindow == NULL) {
printf("window error");
}
//Create renderer for window
SDL_Renderer* gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if (gRenderer == NULL) {
printf("renderer error");
}
bool quit = false; // quit flag
//Event handler
SDL_Event e;
//nice little rendering class
Renderer* renderer = new Renderer();
//World
World* world = new World();
//Texture Atlas
Atlas* atlas = new Atlas(SDL_GetWindowSurface( gWindow), gRenderer);
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
switch(e.type) {
case SDL_QUIT: //User requests quit
quit = true;
break;
}
}
//Clear screen
//SDL_SetRenderDrawColor( gRenderer, 0, 0xFF, 0, 0xFF );
SDL_RenderClear( gRenderer );
renderer->render(gRenderer, atlas, world, SCREEN_WIDTH, SCREEN_HEIGHT);
//Update the surface
SDL_RenderPresent(gRenderer);
//SDL_UpdateWindowSurface( gWindow );
}
delete (world, renderer, atlas);
return 0;
}
This allocates a std::vector with one element of BaseEntity
environment = new std::vector<BaseEntity>(1); // this is where init
then another element of Grass is appended
environment->push_back(Grass()); // adding something to it works fine
but maybe this is the first problem, since the vector only holds BaseEntitys, see What is object slicing?
This accesses the first element of the given vector, and this is not the appended Grass but the default constructed BaseEntity object from new std::vector<BaseEntity>(1)
std::vector<BaseEntity> env = *(world->loaded[x][y]->environment); // here is where the error occurs
Accessing the pointer shouldn't be a problem, because it seems to be initialized properly.
But maybe copying the BaseEntity is the real problem here. I would look into the (copy) constructor of BaseEntity (and maybe Grass) and see, if there is some problematic code.
I don't see an immediate problem with your code (except copying the vector is obviously inefficient), but I do see a problem with your printf debugging.
You should use fprintf(stderr, ...) for debug printfs, so as to avoid stdio buffering, or call fflush(NULL).
The fact that 3 is not printed does not necessarily mean that printf("3") is unreached.
You should avoid printf debugging altogether, and learn to use a real debugger (GDB or LLDB) instead.
If you run your program with Address Sanitizer (-fsanitize=address); it will likely point you straight at the bug.
Finally, when writing in C++, avoid C-style arrays, and especially multi-level arrays. Use vectors instead.
Rewriting this to try to provide some clarity and update the code with some things that have changed.
I am restructuring a project that used SDL2, and have encountered issues trying to create a blank window. I have attempted to structure the project similarly to the original by separating all functionality dealing with SDL_Window into its own class. If I move the call to SDL_CreateWindow into the same class as the event loop or move the event loop to the same class as the window, the window is created and shown as expected, however as it is now, the window appears to be created successfully (SDL_CreateWindow is not returning NULL) and the program doesn't seem to be hanging, but it does not display a window while the program is running.
The SDL_Window is created in the Graphics class and stored in a member variable:
Graphics::Graphics(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
screen = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h,
flags);
status = 0;
if (screen == NULL)
status = 1;
}
Graphics is instantiated in the Window class and stored in a member variable.
Window::Window(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
g = Graphics(title, w,h, flags, status);
}
Window is instantiated in main, and if the window is created successfully, it starts the event loop.
{
int status;
Window window("Mirari", 640,480, SDL_WINDOW_SHOWN, status);
if (status == 0) {
window.eventLoop();
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s", SDL_GetError());
return 1;
}
}
The event loop itself to be thorough (update and draw are both currently empty functions).
void Window::eventLoop() {
SDL_Event ev;
bool running = true;
while (running) {
const int start_time = SDL_GetTicks();
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
//update();
//draw();
std::cout << "." << std::endl;
const int elapsed = SDL_GetTicks() - start_time;
if (elapsed < 1000 / FPS)
SDL_Delay(1000 / FPS - elapsed);
}
}
SDL is initialized with this static function and these flags.
void Window::init(unsigned int sdl_flags, IMG_InitFlags img_flags) {
SDL_Init(sdl_flags);
IMG_Init(img_flags);
TTF_Init();
}
...
Window::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER, IMG_INIT_PNG);
I know that a window can be created in a separate class because the first version of this project did that and it worked, I'm just not sure what has changed that is causing the window not to show up.
As said by some programmer dude, you design is not perfect and should be thought again.
Nevertheless, from what we can see on your code : If the Window constructor is called (and the SDL_Init was called before, which I assume so), then the windows should be created.
From there we only can guess what we can't see (as it's not part of what you are displaying) :
is the definition of SDL_WINDOWPOS_UNDEFINED, the same in both context ?
is the screen variable definition the same in both context ?
is the "screen" used in "update", or "draw" method, and, as uninitialized : it fails
... ?
As you probably are new to development, I suggest you adopt this habit very early : your code should check and report everything it does. A good program is easy to debug, as it says what's wrong
For instance, just after :
screen = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h, flags);
you may want to write something like :
if(!screen)
{
std::cout << "Failed to create window\n";
return -1;
}
or better :
if(!screen)
{
throw std::exception("Failed to create window\n");
}
And so on.
For instance, in your function update, you may want to have something like :
if(!screen)
{
throw std::exception("Unable to update the display as it is uninitialized\n");
}
I assume your application would not end without any comment... but that's a guess
I'm calling SDL_RenderCopy and it gets called and returns normally but doesn't draw anything to the window. Edited to make the question and code clearer. I'm thinking I might be trying to use something beyond its scope and hence it can't be called but this doesn't produce any error so I'm not sure. Here's the simple picture I refer to https://commons.wikimedia.org/wiki/Category:PNG_chess_pieces/Standard_transparent#/media/File:Chess_kdt60.png
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// Recreation of the problem. Doesnt draw anything onto the white screen.
class King{
public:
King(SDL_Renderer *renderer){
SDL_Surface *Piece;
Piece = IMG_Load("Pieces/BK.png"); // I'll attach the picture
king = SDL_CreateTextureFromSurface(renderer, Piece);
SDL_FreeSurface(Piece);
kingRect.h = 100;
kingRect.w = 100;
}
~King(){}
void render(SDL_Renderer *renderer){
SDL_RenderCopy(renderer, king, NULL, &kingRect); // 99% sure the problem is this
}
private:
SDL_Texture *king;
SDL_Rect kingRect;
};
class Game {
public:
Game(const char *title, int sidelength){
isRunning = true;
if(SDL_Init(SDL_INIT_EVERYTHING) != 0) isRunning = false;
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, sidelength, sidelength, SDL_WINDOW_OPENGL);
if(window == NULL) isRunning = false;
renderer = SDL_CreateRenderer(window, -1, 0);
if(!renderer) isRunning = false;
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
}
~Game(){}
void handleEvents(){
//Handles Events. I know this works.
}
}
void update(){};
void render(){
SDL_RenderClear(renderer);
BK.render(renderer);
SDL_RenderPresent(renderer);
}
void clean(){
//Cleans up after. I know this works.
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
}
bool running(){return(isRunning);}
King BK{renderer};
private:
bool isRunning{true};
SDL_Window *window;
SDL_Renderer *renderer;
};
Game *game = nullptr;
int main(int argc, const char *argv[]){
game = new Game("Testing Window", 800);
while(game->running()){
game->handleEvents();
game->update();
game->render();
}
game->clean();
return(0);
}
King BK{renderer}; field gets initialised before your Game::Game finishes and gets a chance to assign a renderer, so it gets NULL instead. NULL is not a valid renderer and can't create textures. If you would have checked for error you would have got Invalid renderer message. Also decent compiler with enabled warnings will tell something like warning: 'Game::renderer' is used uninitialized in this function [-Wuninitialized]; consider enabling better warning levels in your compiler.
Second thing is that you never called IMG_Init with required image formats you intend to load.
Third thing is that code is misformatted and wouldn't compile without modifications. I suggest testing code that you post as MCCVE for still being compilable and reproducing your problem (as MCCVE implies).
My code:
window.cpp
Window::Window(int w, int h, const char *title, const char *icon)
{
height = h;
width = w;
if(SDL_Init( SDL_INIT_EVERYTHING ) == 0)
{
SDL_WM_SetCaption(title, NULL);
SDL_WM_SetIcon(SDL_LoadBMP(icon),NULL);
screen = SDL_SetVideoMode(width, height, 32,
SDL_SWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF);
if(screen == NULL)
{
running = false;
return;
}
fullscreen = false;
}
else
running = false;
return;
}
Window::Window()
{
const SDL_VideoInfo* info = SDL_GetVideoInfo();
screenWidth = info->current_w;
screenHeight = info->current_h;
Window(640, 480, "Flatgu game", "rsc/img/icon.bmp");
}
window.h
class Window
{
public:
Window();
~Window();
int getWidth() {return width;}
int getHeight() {return height;}
bool isFullscreen() {return fullscreen;}
void toggleFullscreen();
private:
Window(int w, int h, const char *title, const char *icon);
bool fullscreen, running;
int height, width, screenWidth, screenHeight;
SDL_Surface *screen;
};
It compiles fine, but then, after compiling, I'm getting this ugly error:
What's the reason of my problem? Why do I get so weird numbers?
My aim is to store original screen resolution for further use (like toggling to fullscreen), and I have to do this before calling SDL_SetVideoMode(). That's why it is in the constructor.
You have a problem with calling SDL Video Functions before actually initializing SDL.
SDL_Init( SDL_INIT_EVERYTHING )
has to be called before
SDL_GetVideoInfo();
In your case you call SDL_GetVideoInfo(); first
const SDL_VideoInfo* info = SDL_GetVideoInfo(); //<-- calls SDL_GetVideoInfo();
screenWidth = info->current_w;
screenHeight = info->current_h;
Window(640, 480, "Flatgu game", "rsc/img/icon.bmp"); //<-- initializes SDL
So the solution is simple; make the call SDL_Init( SDL_INIT_EVERYTHING ) immediately at the start of your program, then you can call SDL_GetVideoInfo(); as much as you like.
You will have to restructure your class Window slightly.
To get the best video mode call SDL_GetVideoInfo before setting up the video (before calling SDL_SetVideoMode).
But you still have to initialize the video subsystem before calling it (SDL_Init(SDL_INIT_VIDEO)).
I know this is old, but there's a big mistake in the code.
Window(640, 480, "Flatgu game", "rsc/img/icon.bmp");
creates a nameless instance of a Window, so the instance that calls it will still have uninitialized variables. It looks like you were trying to use delegating constructors, but in that case the call to the other constructor must be in the member initializer list.
See this page.
I'm using a physics library called Chipmunk for a game that I'm writing.
In my initialize function I initialize the global variable cpSpace space. Then in update I call cpSpaceStep(space, timestep). The prototype for this function is void cpSpaceStep(cpSpace *space, cpFloat dt);. I'm getting a segfault on this function call. I've marked those two function calls in the code below.
The full code is below:
#include "../include/SDL/SDL_image.h"
#include "../include/SDL/SDL.h"
#include "../include/Player.h"
#include "../include/Timer.h"
#include "../include/Block.h"
#include "../include/ImageLoader.h"
#include "../include/chipmunk/chipmunk.h"
#include <string>
//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
//The frame rate
const int FRAMES_PER_SECOND = 60;
SDL_Event event;
SDL_Surface *screen = NULL;
SDL_Surface *player_img = NULL, *block_img = NULL;
Player *player;
Timer fps;
cpSpace *space;
bool quit = false;
void initialize();
void update();
int main( int argc, char* argv[] )
{
initialize();
update();
return 1;
}
void initialize()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
}
//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
//If there was an error in setting up the screen
if( screen == NULL )
{
}
//Set the window caption
SDL_WM_SetCaption( "Move the Dot", NULL );
cpVect gravity = cpv(0, 100);
//******************cpSpacenew()*****************
//This is where space is init'ed
space = cpSpaceNew();
//***********************************************
}
void update()
{
//While the user hasn't quit
while( quit == false )
{
//Start the frame timer
fps.start();
while( SDL_PollEvent( &event ) )
{
//Handle events for the dot
player->handle_input( &event );
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}
}
player->update();
cpFloat timeStep = 1.0/FRAMES_PER_SECOND;
//************************Segfault**********************************************
cpSpaceStep(space, timeStep);
//******************************************************************************
//Cap the frame rate
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
}
}
Where's your cpInitChipmunk() call? Without that, it's likely that cpSpaceNew() may well return NULL (or junk).
Easy enough to check. Immediately after the call to cpSpaceNew(), insert a:
printf ("%p\n", space);
(or something equivalent, to see what the value is.
You may also want to do that immediatley before trying to use it as well, just in case something corrupts it.
Could be because space is NULL when you call cpSpaceStep(). And in cpSpaceStep() function, an attempt is done to dereference the pointer which is NULL. Check whether space is properly initialized in initialize().