LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 04-19-2010, 07:52 PM   #1
prushik
Member
 
Registered: Mar 2009
Location: South Korea
Distribution: Lubuntu, BetterLinux
Posts: 364

Rep: Reputation: 29
Seg Fault. Memory address not being passed to function.


I am writing a game in C with SDL. I can successfully display one image on the screen and animate it. However, I am having a lot of issues getting the background to display using the same method. I was asking for help on SDL related forums, but I determined that the issue is not SDL related, and it is actually a pointer issue. However, I can't find where I'm going wrong.

Code:
#include <SDL/SDL.h>

struct image
{
   const char *fname;
   SDL_Surface *surface;
};

struct animation
{
   struct image image;

   struct animation *next;
};

struct stats
{
   char      name[32];
   unsigned int   attack,
         defense,
         health,
         max_ammo;
};

struct physics
{
   double   x, y,
      dir;
};

struct character
{
   struct stats status;
   struct physics physics;
   struct image image;
   struct animation *left,*right,*up,*down,*active;
};

struct character Main, BG;


void windowInit(const char * title, short unsigned int width, short unsigned int height)
{
   SDL_Init(SDL_INIT_VIDEO);

   SDL_WM_SetCaption(title, title);

   screen = SDL_SetVideoMode(width, height, 16, SDL_DOUBLEBUF);
//   screen = SDL_SetVideoMode(width, height, 16, SDL_DOUBLEBUF | SDL_FULLSCREEN);

   return;
}

void display()
{
   SDL_Flip(screen);

   return;
}

void show(double x, double y, struct image obj)
{
   SDL_Rect src, dest;
 
   printf("%d:%d\n",obj,obj.surface);
 
   src.x = 0;
   src.y = 0;
   printf("1\n");
   src.w = obj.surface->w;
   src.h = obj.surface->h;
   printf("2\n");
   
   printf("3\n");
   dest.x = x;
   dest.y = y;
   printf("4\n");
   dest.w = obj.surface->w;
   dest.h = obj.surface->h;

   SDL_BlitSurface(obj.surface, &src, screen, &dest);

   return;
}

struct animation *animation_create_frames(unsigned short int frames)
{
   int i;
   struct animation *tmp, *start;
   
   start=malloc(sizeof(struct animation));
   tmp=start;
   for (i=1;i<frames;i++)
   {
      tmp->next=malloc(sizeof(struct animation));
      tmp=tmp->next;
   }
   tmp->next=start;
   
   return start;
}

void delay(Uint32 i)
{
   SDL_Delay(i);

   return;
}

void loadImage(const char *fname, struct image *obj)
{
   obj->fname=fname;
   SDL_Surface *temp = SDL_LoadBMP(fname);
   obj->surface = SDL_DisplayFormat(temp);
   SDL_FreeSurface(temp);
   
   //SDL_SetAlpha(obj->surface, SDL_SRCALPHA | SDL_RLEACCEL, 0xFF);
   SDL_SetColorKey(obj->surface, SDL_SRCCOLORKEY, SDL_MapRGB(obj->surface->format, 0x0, 0xFF, 0x0));
   
   printf("%d::%d\n",obj,obj->surface);
   return;
}

void gameInit()
{
   BG.active=malloc(sizeof(struct animation));
   loadImage("./images/testbg.bmp",&BG.active->image);

   Main.down=animation_create_frames(4);
   loadImage("./images/c1_1.bmp", &Main.down->image);
   loadImage("./images/c1_2.bmp", &Main.down->next->image);
   loadImage("./images/c1_1.bmp", &Main.down->next->next->image);
   loadImage("./images/c1_3.bmp", &Main.down->next->next->next->image);
   Main.active=Main.down;
   
   Main.physics.x=100;
   Main.physics.y=200;
   
   return;
}

void gameRender()
{
   printf("%d:%d\n",Main.active->image,Main.active->image.surface);
   show(Main.physics.x, Main.physics.y, Main.active->image);
   Main.active=Main.active->next;
   
   printf("%d:%d\n",BG.active->image,BG.active->image.surface);
   show(0,0,BG.active->image);
   
   display();
   
   return;
}



int quit=false;

int main ( int argc, char *argv[] )
{
   windowInit("The Lesser Evil",640,480);
   
   gameInit();
   
   #ifdef DEBUG
   SDL_version ver;
   
   // Prints the compile time version
   SDL_VERSION(&ver);
   printf("SDL Version: %u.%u.%u\n", ver.major, ver.minor, ver.patch);

   // Prints the run-time version
   ver = *SDL_Linked_Version();
   printf("SDL Runtime Version: %u.%u.%u\n", ver.major, ver.minor, ver.patch);
   #endif

   while (!quit)
   {
      gameRender();
      delay(1000/5);
   }
   
   
   return 0x14;
}

Ok, there it is. I added a bunch of printf to determine where and why this is happening. I changed "struct image backdrop" to "struct character BG" so I could do the exact same thing with Main and BG. Main works, BG still does not. I also use a circularly-linked list for an animation. Here is some sample output from the program:

Code:
13733488::13808336
13733760::13734000
13733792::13734240
13733824::13739360
13733856::13739600
SDL Version: 1.2.13
SDL Runtime Version: 1.2.13
4199076:13734000
4199076:13734000
1
2
3
4
4199056:13808336
0:0
1
Segmentation fault
The first few lines confirm that the images are getting loaded correctly. Then my SDL version numbers. Then the memory addresses of Main.active and Main.active->image before and after it gets passed to show(). Then 1 2 3 4 showing that show() didn't crash that time.
As you can see from the last 3 lines before the segfault, the problem is occurring in the show function. I try to pass BG to it, but the function sees it as 0. weird because when I do the exact same thing with Main it works fine. If I just comment out the line where I show(BG), then it runs fine and I see my little walking guy on a black screen. The memory address of BG.active->image isn't getting passed into show(), I confirmed this with GDB. What is going on?
 
Old 04-20-2010, 10:43 AM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,464

Rep: Reputation: 845Reputation: 845Reputation: 845Reputation: 845Reputation: 845Reputation: 845Reputation: 845
Code:
void show(double x, double y, struct image obj)
{
   SDL_Rect src, dest;
 
   printf("%d:%d\n",obj,obj.surface);
Quote:
The memory address of BG.active->image isn't getting passed into show()
obj isn't a pointer.

Nor is obj a number, so that printf doesn't make sense. You should compile with -Wall and -Wextra so gcc will warn you about incorrect format strings. Also it would help if you added the name of the variable you are printf'ing because right now it's difficult to follow what the output means.
 
Old 04-20-2010, 11:15 AM   #3
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,094

Rep: Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111
I agree with ntubski regarding the error in the printf. But I don't see how that error invalidates the conclusion you reached about the malfunction. You seem to have pretty solid evidence that BG.active->image is valid right before being passed into show() as obj, but obj is not valid in show().

I really doubt that the difference is BG vs. MAIN. I think the difference is
0,0 vs. Main.physics.x,Main.physics.y as if the compiler didn't know that it must cast 0,0 into 0.0,0.0

I think the earlier definition of show() should make the compiler know it must do that cast. I'm not sure what rule of C I'm missing. But given the evidence that the compiler doesn't know, you ought to try doing it yourself:
use
Code:
show(0.0,0.0,BG.active->image);
instead of
Code:
show(0,0,BG.active->image);
BTW, I really don't like passing the image to show() by value rather than by pointer. But I don't see any way that can be part of the problem.

Last edited by johnsfine; 04-20-2010 at 11:19 AM.
 
Old 04-21-2010, 12:28 AM   #4
prushik
Member
 
Registered: Mar 2009
Location: South Korea
Distribution: Lubuntu, BetterLinux
Posts: 364

Original Poster
Rep: Reputation: 29
Quote:
Originally Posted by johnsfine View Post
I agree with ntubski regarding the error in the printf. But I don't see how that error invalidates the conclusion you reached about the malfunction. You seem to have pretty solid evidence that BG.active->image is valid right before being passed into show() as obj, but obj is not valid in show().

I really doubt that the difference is BG vs. MAIN. I think the difference is
0,0 vs. Main.physics.x,Main.physics.y as if the compiler didn't know that it must cast 0,0 into 0.0,0.0

I think the earlier definition of show() should make the compiler know it must do that cast. I'm not sure what rule of C I'm missing. But given the evidence that the compiler doesn't know, you ought to try doing it yourself:
use
Code:
show(0.0,0.0,BG.active->image);
instead of
Code:
show(0,0,BG.active->image);
BTW, I really don't like passing the image to show() by value rather than by pointer. But I don't see any way that can be part of the problem.
Oh my God! That was the problem the whole time?!?! That's ridiculous! Is this a bug in the compiler? Or is this normal behavior? I have never heard of this before.
Anyway, I tried
Code:
show(0.0,0.0,BG.active->image);
and it worked perfectly. I'm just having a hard time believing that gcc would pass an int to a function that wants a double and not even warn me about it. Thank you johnsfine! You saved this project!
BTW. Correct me if I'm wrong. I probably am, this is probably my (forced) Java classes polluting my memory, but BG.active->image should never get passed by value, shouldn't it get passed by reference? I think I'm mixing up Java and C. If it is getting passed by value, then I've made a horrible mistake, I'm wasting quite a lot of resources.
I WAS passing a pointer, but I changed it once I started having problems. So, fortunately, this is the only place in my code where I do this.
 
Old 04-21-2010, 06:39 AM   #5
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,094

Rep: Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111Reputation: 1111
Quote:
Originally Posted by prushik View Post
Is this a bug in the compiler?
I really doubt that.

I was wondering if it was a difference between the code you posted and the code you tested. For example, did you actually have show() and gameRender() in different source files, so that the compiler compiles gameRender() without the declaration of show(). Then the behavior would be expected. Neither the compiler nor the linker would complain that the signature for show() assumed by gameRender() fails to match the actual signature.

If what you tested was exactly what you posted, I don't understand the compiler behavior. But that is not enough of a reason to jump to the conclusion of a compiler bug.

Quote:
this is probably my (forced) Java classes polluting my memory, but BG.active->image should never get passed by value, shouldn't it get passed by reference?
It either gets passed by value or it gets copied and the copy gets passed by reference (which of those actually happens is an implementation detail internal to the compiler). It certainly does not pass the original by reference.

Quote:
I think I'm mixing up Java and C.
I think so.

Quote:
If it is getting passed by value, then I've made a horrible mistake, I'm wasting quite a lot of resources.
The object consisted of only two pointers. Pass by value adds just a little cost to the calling function. If it really passes by value (rather than pass a copy by reference) then it saves a little cost (compared to the usual pass by pointer) within the called function. In this case it doesn't net to any big difference.

I just think it is a bad practice. In other situations, it will cost a lot and/or give unexpected results.
 
  


Reply

Tags
fault, sdl, segfault, segmentation fault


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
seg fault / mem fault - in cron, but works in shell? kauaikat Red Hat 1 04-29-2008 04:24 PM
seg fault / mem fault - in cron, but works in shell? kauaikat Linux - Software 1 04-29-2008 08:21 AM
seg fault when strtok on static memory c++ gearoid_murphy Programming 5 04-30-2007 11:04 AM
seg. fault when allocating memory via a pointer inside a struct elmafiacs Programming 4 02-20-2005 07:26 AM


All times are GMT -5. The time now is 07:20 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration