DaemonForums  

Go Back   DaemonForums > Miscellaneous > Programming

Programming C, bash, Python, Perl, PHP, Java, you name it.

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 12th September 2011
xmorg xmorg is offline
Real Name: Tim Cooper
Fdisk Soldier
 
Join Date: Sep 2010
Location: San Diego
Posts: 56
Default Pointer to structs, C

Im getting an error when compiling my little "roguelike" attempt game
Code:
gcc -o rogue -lncurses *.c
maps.c: In function 'worldgen':
maps.c:131: error: incompatible type for argument 1 of 'regiongen'
*** Error code 1
Here is how its setup. First there are the structs
Code:
typedef struct s_region {
  long width;
  long height;
  char *mapname;
  char **data;
} region;

typedef struct s_worldmap {
  long width;
  long height;
  char *mapname;
  char **data; //The characters of the map.
  //Region structs.
  region **wregions; //a w*h array of regions
} worldmap;
Then a function named "worldgen"
Code:
int worldgen(worldmap *wm, int height, int width, int mtype) {
....
wm = (worldmap *)malloc( sizeof(worldmap) );
wm->wregions = (region **) malloc(wm->height * sizeof(region *)); //REGIONS
  for(i = 0; i < height; i++)
    {
      wm->wregions[i] = (region *) malloc(wm->width * sizeof(region));
    }
....somewhere within my "for loop"
regiongen(wm->wregions[y][x], wm->height, wm->width, wm->data[y][x]);

regiongen's prototype
int regiongen(region *rm, int height, int width, char maptype);

my question is, is the argument, wm->wregions[y][x] not a pointer to struct?

Last edited by ocicat; 12th September 2011 at 06:18 AM. Reason: Using [code] & [/code] tags makes life simpler on your readers...
Reply With Quote
  #2   (View Single Post)  
Old 12th September 2011
teig teig is offline
Port Guard
 
Join Date: May 2008
Posts: 20
Default

No, wregions[y] is a region*.

data and wregions are the same (**), but declared differently in regiongen.

I would regard wregions as a one-dimensional array of pointers.
If you need to look at it as a two-dimensional array you will have to apply some math to the indexing.
Reply With Quote
  #3   (View Single Post)  
Old 12th September 2011
ocicat ocicat is offline
Administrator
 
Join Date: Apr 2008
Posts: 3,318
Default

Quote:
Originally Posted by xmorg View Post
my question is, is the argument, wm->wregions[y][x] not a pointer to struct?
No, wm->wregions[y][x] is a region.
  • wm->wregions is the beginning address of an array of region pointers. This array forms one dimension. Given that y is used as the index, one can visualize this array as denoting the vertical axis.
  • Each wm->wregions[y] element (where each is a pointer to another array of region's...) points to another singly-dimensioned array which can be visualized as representing the horizontal axis. Note the symbolism of x.

Last edited by ocicat; 12th September 2011 at 07:28 AM.
Reply With Quote
  #4   (View Single Post)  
Old 18th September 2011
xmorg xmorg is offline
Real Name: Tim Cooper
Fdisk Soldier
 
Join Date: Sep 2010
Location: San Diego
Posts: 56
Default

Hey everyone thanks for the response. Situation resolved by using address of

regiongen(&wm->wregions[y][x], wm->height, wm->width, wm->data[y][x]);

Now, im writing all of my regions to file, the file gets to about 2.7 megabytes and the program crashes(in the middle of writing a region).... some kinda overflow? what is it? Ive tried fputc, and fputs... hmmm.
Reply With Quote
  #5   (View Single Post)  
Old 18th September 2011
ocicat ocicat is offline
Administrator
 
Join Date: Apr 2008
Posts: 3,318
Default

Quote:
Originally Posted by xmorg View Post
H...the program crashes(in the middle of writing a region).... some kinda overflow? what is it? Ive tried fputc, and fputs... hmmm.
We haven't seen the code, so it is difficult to say what is the root cause, but things you will want to explore include:
  • Ensure all regions have been initialized. It appears you are doing a lot of dereferencing in your code, &:
    • reading from a nonzero random address will yield garbage. At this point, it becomes a question of whether the bit patterns found at such addresses yield valid values.
    • writing to nonzero random addresses will generate a fault.
    Your structures contain many string addresses. If these addresses have not been initialized or assigned the address of memory acquired through malloc(), etc, then they are uninitialized as well.
  • Look at how much data is on the stack. At compilation, the size of the stack will be set. For "normal" usage, the system default should be adequate, but like all C-like arrays, array boundaries can be exceeded.
My suggestion is to write code which will output a region to stdout, or at least chosen parts. The purpose of this is to provide you a means of validating any arbitrary region structure which is being maintained. Until you can say with certainty that all structures contain expected data, dereferencing problems will continue to lurk.
Reply With Quote
  #6   (View Single Post)  
Old 23rd September 2011
xmorg xmorg is offline
Real Name: Tim Cooper
Fdisk Soldier
 
Join Date: Sep 2010
Location: San Diego
Posts: 56
Default

Thanks ocicat!
Code here http://www.cooperlabs.net/dfroguelike.tar.gz

I have managed to work around the save crash by having it create 40 "region files" when saving the world instead of one giant save file. The program now works up to the character generator, and only crashes now in macosx (works fine in bsd)

dont laugh at my code, i consider myself and "enthusiastic novice at C"

Edit: (gdb on macosx)
Code:
Program received signal EXC_BAD_ACCESS, Could not access memory.                
Reason: KERN_INVALID_ADDRESS at address: 0x00007fff6076d300                     
0x00007fff80c8ec00 in strlen ()

Last edited by ocicat; 23rd September 2011 at 02:02 PM. Reason: Screen output is easier to read by using [code] & [/code] tags.
Reply With Quote
  #7   (View Single Post)  
Old 23rd September 2011
ocicat ocicat is offline
Administrator
 
Join Date: Apr 2008
Posts: 3,318
Default

Quote:
Originally Posted by xmorg View Post
Code:
Program received signal EXC_BAD_ACCESS, Could not access memory.                
Reason: KERN_INVALID_ADDRESS at address: 0x00007fff6076d300                     
0x00007fff80c8ec00 in strlen ()
...which is the tell-tale sign of a string which isn't NULL-terminated.

I haven't looked at your code yet (maybe this weekend if it is relatively small...), but is there a reason why you are creating such an elaborate structure based on pointers, calls to malloc(), etc.? Why not pre-allocate a fixed size array at compilation time? There can be valid reasons for allocating everything from the heap, but you take on deciphering the structure as a result.
Reply With Quote
  #8   (View Single Post)  
Old 25th September 2011
ocicat ocicat is offline
Administrator
 
Join Date: Apr 2008
Posts: 3,318
Default

Quote:
Originally Posted by xmorg View Post
Code here http://www.cooperlabs.net/dfroguelike.tar.gz

I have managed to work around the save crash by having it create 40 "region files" when saving the world instead of one giant save file. The program now works up to the character generator, and only crashes now in macosx (works fine in bsd)
I looked briefly at your code. Given the behavior & error messages mentioned, I still am of the opinion that your code is walking into unallocated memory. Where, I did not discern. However, here are a few more thoughts on what can be done to find the problems:
  • I didn't determine whether wm->height & wm->width were being assigned only once, but these values are frequently used as upper bounds in for-loops when iterating through the overall structure. You will want to make sure these values aren't changed past the point of allocation.
  • I did notice that in write_world_file(), wm->height & wm->width are defined as type long, but the indexes used were of type int. Making the indexes the same type as the upper bound is a good idea.
  • Write independent test code on the side which simply creates the structure with anticipated fixed sizes, write to each location in the structure, and read & write to a file. Start with very small sizes & ensure that reading & writing works. Once this is verified, increase the sizes & ensure that reading & writing still works. I still believe that some memory access is happening past what has been allocated. A simplified test case will make it easier to pinpoint the problem.
Reply With Quote
  #9   (View Single Post)  
Old 22nd March 2012
iostreamer iostreamer is offline
New User
 
Join Date: Mar 2012
Posts: 7
Default

Have you run it against valgrind? What is the output?
Reply With Quote
Old 24th March 2012
xmorg xmorg is offline
Real Name: Tim Cooper
Fdisk Soldier
 
Join Date: Sep 2010
Location: San Diego
Posts: 56
Default

Hey thanks guys. I am trying valgrind now.
I also fixed the broken link on my code. IS it possible to have pointers to structs within pointers to structs within pointers to structs etc???

I am trying to do this which has a compile error.
Code:
//gr->mtiles[y][x]->rcTiles.w = gr->tilew;
 //gr->mtiles[y][x]->rcTiles.h = gr->tileh;
gr is a pointer to struct GameRes
inside gr is mtiles, a pointer to struct Tile
inside Tile is rcTiles a pointer to struct SDL_Rect (which as members w and h)

mtiles is an array created with malloc like so:
Code:
gr->mtiles = (Tile **) malloc(sizeof(Tile *)); //malloc new Tile struct
  for(i = 0; i < MAPSIZE; i++) //malloc new Tile sturct
    {
      gr->mtiles[i] = (Tile *) malloc(MAPSIZE * sizeof(Tile));
      gr->mtiles[i]->rcTiles = (SDL_Rect *) malloc(sizeof(SDL_Rect));
    }
Is this just too complicated? Am I making too much work for miself?

Last edited by ocicat; 24th March 2012 at 05:10 AM. Reason: Use [code]/[/code] tags to make code more readable.
Reply With Quote
Old 24th March 2012
ocicat ocicat is offline
Administrator
 
Join Date: Apr 2008
Posts: 3,318
Default

Quote:
Originally Posted by xmorg View Post
IS it possible to have pointers to structs within pointers to structs within pointers to structs etc???
Yes, but recognize what you are really trying to ask:

Is it possible to store an address of a nested structure within an enclosing structure which will be set sometime during runtime?
The answer is still "yes".
Quote:
Am I making too much work for miself?
As mentioned before, it appears that you are writing all the code at once, then realizing that it needs to be debugged. Yes, this may appear daunting.

The solution is to break the problem down into smaller portions, & debug them one at a time. This is the secret of writing large applications -- break it down into more managable subsystems, & test, test, test.

Decomposition is cool.
Reply With Quote
Reply

Thread Tools
Display Modes

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 On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
OpenBSD OpenBSD Reliability Fix: kernel NULL pointer dereference in getsockopt() J65nko News 0 28th October 2009 11:56 PM
c++: writing to the *this pointer? robbak Programming 2 23rd October 2009 06:12 PM


All times are GMT. The time now is 02:40 PM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick