4 Replies - 723 Views - Last Post: 22 February 2013 - 11:37 AM Rate Topic: -----

#1 InterNoctem  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 21-February 13

Segfault on SDL_Flip

Posted 21 February 2013 - 10:32 PM

Hello, this is my first post on DiC, it seems like a great community. I suppose I should give a little background on myself. I am trying to teach myself to program using C as a hobby (for the forseeable future) and I have been independently studying various computer science topics on and off for a few years now. I've managed to expand my understanding to a somewhat decent level but my knowledge is full of gaps that I hope to fill in time, so for all intents and purposes I'm a beginner to programming and especially C (I've dabbled in a few other languages but have forgotten everything). I feel pretty comfortable with the syntax of C and can complete basic tasks, also I welcome replies that are "above my head" so I can have an opportunity to pick up on new leads to learn about. I hope to gain a comfortable competence in coding and to eventually become a productive member of the growing software community.

Now for the problem. I'm trying to learn to use SDL for a project to create a simple game as a goal to focus on for practicing C. I'm following the Lazy Foo tutorials but trying to modify them for C instead of C++ which, so far, doesn't seem too fundemental to the concepts. I recently got stuck on tutorial 4 when I attempted to change the code from being centered around global variables to using local variables, namely the SDL_Surface *screen. I couldnt seem to find any straightforward answers on changing functions to work with local variables but I tried my best to pass *screen into a few functions and pass it on to be displayed. All was going well up until SDL_Flip which gave me a segmentation fault on execution of the program. Here is what I have:

// included header files
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

// constants
#define SCREEN_WIDTH 600
#define SCREEN_HEIGHT 600
#define SCREEN_BPP 32

// prototypes
int init(SDL_Surface *screen);
int clean(SDL_Surface *screen);
void apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination);
SDL_Surface *load_image(char* filename);


int main(int argc, char **argv)
{
	SDL_Surface *screen = 0;
	SDL_Event event;
	int quit = 0;

	if(init(screen) != 0)
	{
		return(1);
	}
	apply_surface(0, 0, load_image("./textures/tile.bmp"), screen);
	if(SDL_Flip(screen) != 0)
	{
		fprintf(stderr, "Error, failed to flip screen");
		return(1);
	}
	while(quit == 0)
	{
		while(SDL_PollEvent(&event))
		{
			if(event.type == SDL_QUIT)
			{
				quit = 1;
			}
		}
	}
	clean(screen);
	return(0);
}
/* Initializes SDL and screen surface. */
int init(SDL_Surface *screen)
{
	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
	{
		fprintf(stderr, "Error, failed to initialize SDL.\n");
		return(1);
	}

	screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);

	if(screen == 0)
	{
		fprintf(stderr, "Error, failed to set SDL_Surface screen.\n");
		return(1);
	}
	return(0);
}
/* Frees screen and quits SDL. */
int clean(SDL_Surface *screen)
{
	SDL_FreeSurface(screen);
	SDL_Quit();
	return(0);
}
/* Loads image into SDL_Surface from file. Takes file name as a parameter and returns
   an SDL_Surface loaded with image. */
SDL_Surface *load_image(char* filename)
{
	SDL_Surface *loaded_image = 0;
	SDL_Surface *optimized_image = 0;

	loaded_image = IMG_Load(filename);
	
	if(loaded_image != 0)
	{
		optimized_image = SDL_DisplayFormat(loaded_image);
		SDL_FreeSurface(loaded_image);
	}
	else
	{
		fprintf(stderr, "Error, loaded_image is NULL.\n");
	}

	return(optimized_image);
}
/* Blits an SDL_Surface onto another at a specified offset. Takes the x and y location
   of the rectangle surface, the surface to apply, and the surface to apply to as parameters. */
void apply_surface(int x, int y, SDL_Surface *source, SDL_Surface *destination)
{
	SDL_Rect offset;

	offset.x = x;
	offset.y = y;

	SDL_BlitSurface(source, 0, destination, &offset);
}



I stepped it through gdb (though I'm not very experienced with it yet) and triend printing *screen at each line after it's declaration. Immediately after it was declared it printed a (presumably) valid pointer but to my surprise the very next line it switched to null and continued to remain null the rest of the program. I found that when I removed the SDL_Flip block it no longer gave me a segmentation fault. I don't know exactly why the pointer becomes null immediately, unless I've made an error debugging, but I can guess where my problem lies. I'm not very confident about how I passed *screen into my functions as a parameter to avoid using it as a global but I don't understand the proper way to do that. So I suspect I created some memory mess by incorrect use of pointers but I'm lost on how it is giving me a null pointer right off the bat.

Though gdb is saying the fault occurs at SDL_Flip I assume this is an error coming from elsewhere in my code so I'm posting in the C general help. I haven't found any posts that deal with this actual problem and I gave it a long time before giving up and asking for help, just on the edge of slamming my head into the keyboard.

I appreciate any help or suggestions, not only on the content of the code but on my style and structure as well, I'm trying to start off with good habits. Please excuse my lack of proper comments, I'm still learning how to make effective and visually pleasing comments. I'm happy to provide any additional information that may help.

Thank you for your time, I apologize for the lengthy post.

Is This A Good Question/Topic? 0
  • +

Replies To: Segfault on SDL_Flip

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3552
  • View blog
  • Posts: 11,008
  • Joined: 05-May 12

Re: Segfault on SDL_Flip

Posted 21 February 2013 - 10:52 PM

screen on line 20 is local to main(). So the screen that you created/initialized on line 56 never gets returned back to main() and later passed on to the call to SDL_Flip.
Was This Post Helpful? 1
  • +
  • -

#3 InterNoctem  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 21-February 13

Re: Segfault on SDL_Flip

Posted 21 February 2013 - 11:00 PM

Thanks for the reply. I thought line 56 might be the culprit, so then do I need to change init() to an SDL_Surface* type and return screen for it's pointer to be used further in main?
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3552
  • View blog
  • Posts: 11,008
  • Joined: 05-May 12

Re: Segfault on SDL_Flip

Posted 22 February 2013 - 06:24 AM

In general, if you need to return only one value, you return it as the return value of a function, and if you need to return more than one value, you return it through the function parameters using pass by refererence instead of pass by value.

int DoMultiplication(int a, int B)/>
{
    //$BUG: Possible multiplication overflow
    return a * b;
}

void DoDivision(int a, int b, int * quotient, int * remainder)
{
    //$BUG: Division by zero allowed!
    *quotient = a / b;
    *remainder = a % b;
}



It also depends on the coding style for the code base you are working with. If you are dealing with Windows COM style programming, the return value is always an error/status, code and all return values are passed by reference.

HRESULT DoMultiplication(int a, int b, int * product)
{
    product = a * b;
    //$BUG: Possible multiplication overflow.
    //      Must check and return E_FAILED instead.
    return S_OK;
}

HRESULT DoDivision(int a, int b, int * quotient, int * remainder)
{
    if (b == 0)
        return E_INVALIDARG;

    *quotient = a / b;
    *remainder = a % b;
    return S_OK;
}


Was This Post Helpful? 1
  • +
  • -

#5 InterNoctem  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 21-February 13

Re: Segfault on SDL_Flip

Posted 22 February 2013 - 11:37 AM

Thank you, passing by reference was what I was looking for all along. My code works fine now.
if(init(&screen) != 0)
	{
		return(1);
	}


int init(SDL_Surface **screen)
{
	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
	{
		fprintf(stderr, "Error, failed to initialize SDL.\n");
		return(1);
	}

	*screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);

	if(screen == 0)
	{
		fprintf(stderr, "Error, failed to set SDL_Surface screen.\n");
		return(1);
	}
	return(0);


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1