Thread: Segmentation fault: nested structures and two dimensional struct array allocation

  1. #1
    Registered User
    Join Date
    Mar 2010
    Posts
    44

    Segmentation fault: nested structures and two dimensional struct array allocation

    Hello fellow C programmers,

    this is my first post on this forum so first and foremost, hello everybody.

    Now for my question. The project I am working on is hunter-prey simulation game.
    My error lays in the following part.

    The function below will get parameters from another function. These parameters will tell the function how many meerkats (prey) and hunters will have to be created. It will also tell the function how big the world will be (nSquare, if nSquare is 4, the world will be created as a 4 x 4 world). The function will then allocate these 'animals' (structs). It will also calculate how many ground "animals" (non hunter nor prey animal structs) have to be created by doing nSquare^2 - nHunters - nMeerkats. After this all structs will be allocated. The square will be allocated as a two dimensional array. After that I want to put animals on the world by starting with meerkats. As you can see in the struct square, there can be 5 animals per square. After I'm finished with the meerkats I will put grounds "animals" (notice again that these aren't real animals, I say animals because of the struct name, it's just plain ground) on the world until there are no more. After that the remaining squares will have to be filled with hunters. There is where it goes wrong. When I give the world pointer as a parameter to my print function and try to print the rank of all squares of the world, I get a segmentation fault.

    I'm guessing (I know) I'm doing something wrong at the part where I try to put everything in my 2D array, but I'm stuck at it. Can anyone help me?

    Just ask me if you need more explanation on a part.

    Kind regards,

    boxden

    Struct declaration:

    Code:
    struct Square
    {
    	struct Animal* animal[5]; 
    	struct Room* entrance;
    };
    
    struct Animal
    {
    	char rank;	/* M meerkat H hunter G ground */
    	boolean danger;	 /* default false. when guard detects danger, his 
    					 boolean will turn true, toggling the danger boolean
    					 to true for all animals (meerkats) */
    	boolean isGuard;
    };
    note: typedef int boolean;


    Create surface function and print function:

    Code:
    struct Square *createSurface(int nSquare, int nMeerkat, int nHunter, struct Room *entrance)
    {
    	
    	int i, j, k, meerCounter = 0, huntCounter = 0, groundCounter = 0, nGround;
    	struct Square **square ;
    	struct Animal *meerkat, *hunter, *ground;
    
    	nGround = pow(nSquare, 2) - nMeerkat - nHunter;
    
    	/* CREATION OF THE STRUCTS THE USER GAVE AS INPUT */
    
    	meerkat = (struct Animal*)malloc(nMeerkat * sizeof(struct Animal));
    	hunter = (struct Animal*)malloc(nHunter * sizeof(struct Animal));
    	ground = (struct Animal*)malloc(nGround * sizeof(struct Animal));
    
    	/* INITIALISATION OF THE STRUCTS CREATED ABOVE */
    
    	for (i = 0; i < nMeerkat; i++)
    	{
    		meerkat[i].rank = 'M';
    		meerkat[i].danger = FALSE;
    		meerkat[i].isGuard = FALSE;
    	}
    	meerkat[0].isGuard = TRUE; /* first animal created is a guard */
    
    	for (i = 0; i < nHunter; i++)
    	{
    		hunter[i].rank = 'H';
    		hunter[i].danger = FALSE; /* not important */
    		hunter[i].isGuard = FALSE; /* not important */
    	}
    
    	for (i = 0; i < nGround; i++)
    	{
    		ground[i].rank = 'G';
    		ground[i].danger = FALSE;
    		ground[i].isGuard = FALSE;
    	}
    
    	/* CREATION OF THE WORLD */
    
    	square = (struct Square**)malloc(nSquare * sizeof(struct Square *)); /* two dimensional allocation */
    	for (i = 0; i < nSquare; i++)
    		square[i] = (struct Square*)malloc(nSquare * sizeof(struct Square));
    
    	/* PUTTING ANINALS (MEERKAT, GROUND, HUNTER) ON WORLD */
    
    	for (i = 0; i < nSquare; i++) /* rows */
    	{	
    		for (j = 0; j < nSquare; j++) /* columns */
    		{
    			for (k = 0; k < 5 && meerCounter < nMeerkat; k++, meerCounter++) /* 5 animals per square */
    				square[i][j].animal[k] = &meerkat[meerCounter];
    		}
    	}
    
    	for (i; i < nSquare; i++) /* rows */ /* I want i to continue where it stopped at the previous for loop */
    	{
    		for (j; j < nSquare; j++) /* columns */
    		{
    			for (k = 0; k < 5 && groundCounter < nGround; k++, groundCounter++) /* 5 animals per square */
    				square[i][j].animal[k] = &ground[groundCounter];
    		}
    	}
    
    	for (i = nSquare - 1; i > 0; i--)
    	{
    		for (j = nSquare - 1; j > 0; j--)
    		{
    			for (k = 0; k < 5 && huntCounter < nHunter; k++, huntCounter++)
    				square[i][j].animal[k] = &hunter[huntCounter];
    		}
    	}	
    	
    	/* first animal created was a guard, first animal is on first square so this square will be an entrance */
    	/* has to point to an exit */
    	square[0][0].entrance = entrance;
    	
    	print(square, nSquare);
    	
    	return (&square[0][0]);
    }
    
    void allocIni()
    {
    	/* allocate and ini stuff in here and give pointers back to surface function */
    }
    
    void print(struct Square **world, int nSquare)
    {
    	int i, j, k;	
    	
    	for (i = 0; i < nSquare; i++)
    	{	
    		for (j = 0; j < nSquare; j++)
    		{
    			for (k = 0; k < 5; k++)
    			{
    				printf("RANK: %c X: %i Y: %i Nde animal: %i \t", world[i][j].animal[k]->rank, i, j, k);
    			}
    			printf("\n");
    			
    		}
    	}
    }

  2. #2
    Registered User
    Join Date
    Mar 2010
    Posts
    44
    To make it a bit easier and to reduce the amount of code, what is wrong with this:

    Code:
    	/* PUTTING ANINALS (MEERKAT, GROUND, HUNTER) ON WORLD */
    
    	for (i = 0; i < nSquare; i++) /* rows */
    	{	
    		for (j = 0; j < nSquare; j++) /* columns */
    		{
    			for (k = 0; k < 5 && meerCounter < nMeerkat; k++, meerCounter++) /* 5 animals per square */
    				square[i][j].animal[k] = &meerkat[meerCounter];
    		}
    	}
    
    	for (i; i < nSquare; i++) /* rows */ /* I want i to continue where it stopped at the previous for loop */
    	{
    		for (j; j < nSquare; j++) /* columns */
    		{
    			for (k = 0; k < 5 && groundCounter < nGround; k++, groundCounter++) /* 5 animals per square */
    				square[i][j].animal[k] = &ground[groundCounter];
    		}
    	}
    
    	for (i = nSquare - 1; i > 0; i--)
    	{
    		for (j = nSquare - 1; j > 0; j--)
    		{
    			for (k = 0; k < 5 && huntCounter < nHunter; k++, huntCounter++)
    				square[i][j].animal[k] = &hunter[huntCounter];
    		}
    	}

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Hi boxden and welcome to the forum.

    Since no one has answered your question yet, on the possibility that no one does, let me explain why I did not.

    Quote Originally Posted by boxden View Post
    blah blah blah blah blah ...I get a segmentation fault.
    From the looks of things, you are certainly at a point where you should be attempting to debug the problem in some manner, but I see no mention of this.

    So it's time to learn! One way is to just throw in some fprintf(stderr, "...) to examine the data you are working with (either that or "printf(); fflush(stdout);" -- you need to make sure the output is flushed and not buffered, stderr is not buffered, and you can flush stdout).

    Sometimes printf is the best way to go, but more often a better (and easier) possibility is use a for real dedugger. If you are on linux, compile:

    gcc -g mycode.c

    So the output file is called a.out. Now:

    gdb ./a.out

    When the command prompt appears, type "run". After the segfault, you will hopefully be told the exact line which caused it. If instead it refers to a line from a library file, type "bt" (for backtrace). The #1 line at the top of the backtrace will be a line in your program.

    It's not a for sure solution, but it will certainly allow you to focus more on the actual problem rather than all the "blah blah blah". Meaning you can then at least ask as a more concise and specific question.
    Last edited by MK27; 03-03-2010 at 03:24 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    Registered User
    Join Date
    Mar 2010
    Posts
    44
    Hey MK27

    I acctually did debug in a way that i printed some printfs and ran through my code. I just posted all of the other code so people could understand it better. But that was probably a bad idea.

    Anyway, I've posted the for loops where the error is created. Thank you for your help though, I will keep that in mind next time I have no clue on where to start looking.

Popular pages Recent additions subscribe to a feed

Tags for this Thread