#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    13
    Rep Power
    0

    Segmentation fault


    I've been working of a neural network that does ai for tic tac toe. I can only compile when I'm at school, so I wrote this code without testing it. After sorting through all the syntax errors I have a segmentation fault. I isolated it down to a single line where it occurs, but I cannot figure out why. its in the return statement in the function moveNN. Here is the code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    //DNA = 27*7+7*8+8*7+7*8+8*8
    #define DNA 421
    #define POPSIZE 30
    
    double mutationRate = 10.0/DNA;
    float *genes[POPSIZE];
    int board[9] = {0 * 9};
    int fitSum[POPSIZE];
    int fullBoard = 0;
    float *tempGenes[POPSIZE];
    
    int main()
    {
    	int genNum = 1;
    	srand(100000000);
    	printf("in main\n");
    	initPop();
    	findFitness();
    	while(0==0)
    	{
    		printf("Generation: %d \n", genNum);
    		newGeneration();
    		findFitness();
    	}
    	return 0;
    }
    
    void initPop()
    {
    	int member;
    	for (member=0; member < POPSIZE; member++)
    	{
    		genes[member] = (float*) malloc(sizeof(float)*DNA);
    		tempGenes[member] = (float*) malloc(sizeof(float)*DNA);
    	}
    	for (member=0; member < POPSIZE; member++)
    	{
    		for (int synapse = 0; synapse < DNA; synapse++)
    		{
    			genes[member][synapse] = ((float) rand() / (float) RAND_MAX)*2 -1;
    		}
    	}
    	printf("inited pop\n");
    }
    
    int maxOfFitnessIndex()
    {
    	int max = 0;
    	for (int index = 0;index < POPSIZE;index++)
    	{
    		if(fitSum[max] < fitSum[index])
    		{
    			max = index;
    		}
    	}
    	return max;
    }
    
    void findFitness()
    {
    	int fit = 0;
    	for (int tested = 0;tested < POPSIZE;tested++)
    	{
    		fit = 0; 
    		for (int challenger = 0;challenger < POPSIZE;challenger++)
    		{
    			fit += playTTT(genes[tested],genes[challenger]);
    		}
    		fitSum[tested] = fit;
    	}
    }
    
    int playTTT(int player1[], int player2[])
    {
    	int move;
    	for (int i = 0; i < 0; i++)
    	{
    		board[i] = 0;
    	}
    	while (0==0)
    	{
    		move = moveTTT(player1,1);
    		printf("Yay \n");
    		if(move == 0)
    		{
    			//Loss by illegal move
    			return 0;
    		}
    		if(move == 1)
    		{
    			//Win
    			return 1;
    		}
    		move = moveTTT(moveNN(player2),2);
    		printf("Neural network x2 \n");
    		if(move == 0)
    		{
    			//Loss by illegal move
    			return 1;
    		}
    		if(move == 1)
    		{
    			//Win
    			return 0;
    		}
    	}
    }
    
    int moveTTT(int player[],int mark)
    {
    	printf("Here! \n");
    	int move = moveNN(player);
    	printf("Here! \n");
    	if (board[move]!=0)
    	{
    		return 0;
    	}
    	board[move] = mark;
    	if(winTTT()==1)
    	{
    		printf("Yay! There was a win!! Work justified!! \n");
    		return 1;
    	}
    	return 2;
    }
    
    int winTTT()
    {
    	if (board[0] == board[1] == board[2] != 0){
    		return 1;}
    	if (board[3] == board[4] == board[5] != 0){
    		return 1;}
    	if (board[6] == board[7] == board[8] != 0){
    		return 1;}
    	if (board[0] == board[3] == board[6] != 0){
    		return 1;}
    	if (board[1] == board[4] == board[7] != 0){
    		return 1;}
    	if (board[2] == board[5] == board[8] != 0){
    		return 1;}
    	if (board[0] == board[4] == board[8] != 0){
    		return 1;}
    	if (board[6] == board[4] == board[2] != 0){
    		return 1;}
    	return 0;
    }
    
    int moveNN(int player[])
    {
    	float layer1[] = {0.0 * 7};
    	float layer2[] = {0.0 * 8};
    	float layer3[] = {0.0 * 7};
    	float layer4[] = {0.0 * 8};
    	float layer5[] = {0.0 * 8};
    	int result = 0;
    	for (int input = 0; input < 9; input++)
    	{
    		for (int index1 = 0; index1 < 7; index1++)
    		{
    			layer1[index1] += player[input+7*0]*((board[input] == 0)? 1 : 0);
    			layer1[index1] += player[input+7*1]*((board[input] == 1)? 1 : 0);
    			layer1[index1] += player[input+7*2]*((board[input] == 2)? 1 : 0);
    		}
    	}
    	for (int index1 = 0; index1 < 7; index1++)
    	{
    		for (int index2 = 0; index2 < 8; index2++)
    		{
    			layer2[index2] += player[7*27+index1+index2*7]*((layer1[index1] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index2 = 0; index2 < 8; index2++)
    	{
    		for (int index3 = 0; index3 < 7; index3++)
    		{
    			layer3[index3] += player[7*27+7*8+index2+index3*8]*((layer2[index2] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index3 = 0; index3 < 7; index3++)
    	{
    		for (int index4 = 0; index4 < 8; index4++)
    		{
    			layer4[index4] += player[7*27+7*8*2+index3+index4*7]*((layer3[index3] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index4 = 0; index4 < 8; index4++)
    	{
    		for (int index5 = 0; index5 < 8; index5++)
    		{
    			layer5[index5] += player[7*27+7*8*3+index4+index5*8]*((layer4[index4] >= 0.5)? 1 : 0);
    		}
    	}
    	printf("through layer 5 \n");
    	for (int index5 = 0; index5 < 8; index5++)
    	{
    		result += (layer5[index5] >= 0.5)? 1 : 0;
    	}
    	printf("returning result as %d \n", result);
    	return result;
    }
    
    void newGeneration()
    {
    	int weight = sum();
    	int current[DNA];
    	int random;
    	int count;
    	float *play1;
    	float *play2;
    	for(int player = 0; player < POPSIZE-1; player++)
    	{
    		play1 = genes[getIndex(rand() % weight)];
    		play2 = genes[getIndex(rand() % weight)];
    		random = (((float) rand() / (float) RAND_MAX)*DNA);
    		count = 0;
    		while(count <= random)
    		{
    			tempGenes[player][count]= ( ((float) rand() / (float) RAND_MAX) >= mutationRate)? play1[count]: (((float) rand()) / (float) RAND_MAX)*2 -1;
    		}
    		while(count < DNA)
    		{
    			tempGenes[player][count]= ( ((float) rand() / (float) RAND_MAX) >= mutationRate)? play2[count]: (((float) rand()) / (float) RAND_MAX)*2 -1;
    		}
    	}
    	tempGenes[POPSIZE-1] = genes[maxOfFitnessIndex()];
    	for (int player = 0; player < POPSIZE; player++)
    	{
    		genes[player] = tempGenes[player];
    	}
    }
    
    int sum()
    {
    	int sum = 0;
    	for (int i = 0; i < POPSIZE; i++)
    	{
    		sum += fitSum[i];
    	}
    	return sum;
    }
    
    int getIndex(int top)
    {
    	int index = 0;
    	while(top>=0)
    	{
    		top -= fitSum[index];
    		index += 1;
    	}
    	index -= 1;
    	return index;
    }
    It's 255 lines long sorry, but the fault seems to occur in line 202, I found it with the print statements. Any ideas?
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    Nothing jumps out at me. You're calling that function from two places, one of which is as an argument to another function which itself calls MoveNN.

    Are you able to run this in a debugger? Build a Debug build (unlike a Release build, it will contain extra information that the debugger will need; this is undesirable for released applications because the executable file is not only larger, but it also makes reverse-engineering a bit easier) and run it in the debugger. When it crashes, the debugger will stop at the offending instruction (which could well be in the standard library or other support binary), but the debugger should allow you to trace back through the Call Stack to the line in your code and what calls got you there, along with the values of the local and global variables at that time.

    Now, what I just described is what I do at work in Visual Studio 2008, but if you're using a version of Visual Studio Express (full-featured development environments from Microsoft, downloadable at completely no cost to be paid to Microsoft -- ie, your only cost is your own time and whatever your connection to the Web costs you --, but with some commercial features taken out -- the debugger is still fully functional), then you can still do what I described. If you're using another development environment, if it includes a debugger then I would advise that you make use of that debugger. Printing debug statements has its place (and I do use it often working with embedded projects that attach to a terminal), but that output is buffered so when the program crashes you might not get the last print statements.

    Not knowing much about your program except that the supposedly suspect line of code returns an integer value, accompanied by the observation that arrays are involved, would make me suspect an array that's being accessed out-of-bounds, causing return information in the function's stack frame to be overwritten which in turn would cause an "Air Force branch" ("Off we go into the wild blue yonder ... "; meaning that the return address got clobbered causing the function to return to who-knows-where, namely "off into the wild blue yonder").

    I know it's not much, but hopefully that might get you thinking and asking the right questions.
  4. #3
  5. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,387
    Rep Power
    1871
    > float layer1[] = {0.0 * 7};
    This kind of notation does NOT initialise an array with 7 elements. So all your arrays in moveNN are overflows.
    You have the same issue elsewhere as well.

    If you want 7 elements, all zero, do this
    float layer1[7] = { 0.0 };

    > for (int i = 0; i < 0; i++)
    And this does nothing.

    > if (board[0] == board[1] == board[2] != 0)
    This doesn't do what you seem to think it does - that 3 elements are non-zero.
    Try
    if (board[0] != 0 && board[1] != 0 && board[2] != 0)


    One more thing, try removing some of those global variables, and put them in the only functions which use them.

    The rest should be passed as parameters to all your void functions.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    13
    Rep Power
    0
    Thank you both! I made the changes to my code, but I will have to wait for the school week to compile because I use a school computer that's overprotected, and they don't update it. I'll get back to you if it worked. Thanks again.
  8. #5
  9. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,387
    Rep Power
    1871
    What is the OS of your own machine?
    There are plenty of good and free compilers for all popular desktop/laptop machines.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  10. #6
  11. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,110
    Rep Power
    1803
    Note that tic-tac-toe is a very simple game with a well-known strategy that guarantees either a win or a draw (a draw always occurs if the other player uses the same strategy).

    Your project could be deemed a success if it learns to always draw against a player applying the strategy, and win when the strategy is not played against it -i.e. it has "learned" the strategy, otherwise it may be difficult to determine whether it is truly learned anything. Of course it would be simpler (or at least more deterministic) but perhaps less interesting to just code the strategy. That might then be deemed an "expert system" operating against a set of rules, but hardly deserves the term AI.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    13
    Rep Power
    0
    Update: I fixed all the things Salem said, yet the as I tried to run it again it still had a segmentation fault. Any other ideas?

    Also I have a mac but it's not quite up to date, and I can't update it so Xcode wont work on it.

    And I know there's a perfect strategy, but this is more for the exercise in the thinking, and the ai system.
  14. #8
  15. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,387
    Rep Power
    1871
    > Update: I fixed all the things Salem said, yet the as I tried to run it again it still had a segmentation fault. Any other ideas?
    Yes, post your latest code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    13
    Rep Power
    0
    Sorry I only changed a few things but here it is.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    //DNA = 27*7+7*8+8*7+7*8+8*8
    #define DNA 421
    #define POPSIZE 30
    
    double mutationRate = 10.0/DNA;
    float *genes[POPSIZE];
    int board[9];
    int fitSum[POPSIZE];
    int fullBoard = 0;
    float *tempGenes[POPSIZE];
    
    int main()
    {
    	int genNum = 1;
    	srand(100000000);
    	printf("in main\n");
    	initPop();
    	findFitness();
    	while(0==0)
    	{
    		printf("Generation: %d \n", genNum);
    		newGeneration();
    		findFitness();
    	}
    	return 0;
    }
    
    void initPop()
    {
    	int member;
    	for (member=0; member < POPSIZE; member++)
    	{
    		genes[member] = (float*) malloc(sizeof(float)*DNA);
    		tempGenes[member] = (float*) malloc(sizeof(float)*DNA);
    	}
    	for (member=0; member < POPSIZE; member++)
    	{
    		for (int synapse = 0; synapse < DNA; synapse++)
    		{
    			genes[member][synapse] = ((float) rand() / (float) RAND_MAX)*2 -1;
    		}
    	}
    	printf("inited pop\n");
    }
    
    int maxOfFitnessIndex()
    {
    	int max = 0;
    	for (int index = 0;index < POPSIZE;index++)
    	{
    		if(fitSum[max] < fitSum[index])
    		{
    			max = index;
    		}
    	}
    	return max;
    }
    
    void findFitness()
    {
    	int fit = 0;
    	for (int tested = 0;tested < POPSIZE;tested++)
    	{
    		fit = 0; 
    		for (int challenger = 0;challenger < POPSIZE;challenger++)
    		{
    			fit += playTTT(genes[tested],genes[challenger]);
    		}
    		fitSum[tested] = fit;
    	}
    }
    
    int playTTT(int player1[], int player2[])
    {
    	int move;
    	for (int i = 0; i < 9; i++)
    	{
    		board[i] = 0;
    	}
    	while (0==0)
    	{
    		move = moveTTT(player1,1);
    		printf("Yay \n");
    		if(move == 0)
    		{
    			//Loss by illegal move
    			return 0;
    		}
    		if(move == 1)
    		{
    			//Win
    			return 1;
    		}
    		move = moveTTT(moveNN(player2),2);
    		printf("Neural network x2 \n");
    		if(move == 0)
    		{
    			//Loss by illegal move
    			return 1;
    		}
    		if(move == 1)
    		{
    			//Win
    			return 0;
    		}
    	}
    }
    
    int moveTTT(int player[],int mark)
    {
    	printf("Here! \n");
    	int move = moveNN(player);
    	printf("Here! \n");
    	if (board[move]!=0)
    	{
    		return 0;
    	}
    	board[move] = mark;
    	if(winTTT()==1)
    	{
    		printf("Yay! There was a win!! Work justified!! \n");
    		return 1;
    	}
    	return 2;
    }
    
    int winTTT()
    {
    	if (board[0] != 0 && board[1] != 0 && board[2] != 0){
    		return 1;}
    	if (board[3] != 0 && board[4] != 0 && board[5] != 0){
    		return 1;}
    	if (board[6] != 0 && board[7] != 0 && board[8] != 0){
    		return 1;}
    	if (board[0] != 0 && board[3] != 0 && board[6] != 0){
    		return 1;}
    	if (board[1] != 0 && board[4] != 0 && board[7] != 0){
    		return 1;}
    	if (board[2] != 0 && board[5] != 0 && board[8] != 0){
    		return 1;}
    	if (board[1] != 0 && board[4] != 0 && board[8] != 0){
    		return 1;}
    	if (board[6] != 0 && board[4] != 0 && board[2] != 0){
    		return 1;}
    	return 0;
    }
    
    int moveNN(int player[])
    {
    	float layer1[7] = {0.0};
    	float layer2[8] = {0.0};
    	float layer3[7] = {0.0};
    	float layer4[8] = {0.0};
    	float layer5[8] = {0.0};
    	int result = 0;
    	for (int input = 0; input < 9; input++)
    	{
    		for (int index1 = 0; index1 < 7; index1++)
    		{
    			layer1[index1] += player[input+7*0]*((board[input] == 0)? 1 : 0);
    			layer1[index1] += player[input+7*1]*((board[input] == 1)? 1 : 0);
    			layer1[index1] += player[input+7*2]*((board[input] == 2)? 1 : 0);
    		}
    	}
    	for (int index1 = 0; index1 < 7; index1++)
    	{
    		for (int index2 = 0; index2 < 8; index2++)
    		{
    			layer2[index2] += player[7*27+index1+index2*7]*((layer1[index1] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index2 = 0; index2 < 8; index2++)
    	{
    		for (int index3 = 0; index3 < 7; index3++)
    		{
    			layer3[index3] += player[7*27+7*8+index2+index3*8]*((layer2[index2] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index3 = 0; index3 < 7; index3++)
    	{
    		for (int index4 = 0; index4 < 8; index4++)
    		{
    			layer4[index4] += player[7*27+7*8*2+index3+index4*7]*((layer3[index3] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index4 = 0; index4 < 8; index4++)
    	{
    		for (int index5 = 0; index5 < 8; index5++)
    		{
    			layer5[index5] += player[7*27+7*8*3+index4+index5*8]*((layer4[index4] >= 0.5)? 1 : 0);
    		}
    	}
    	for (int index5 = 0; index5 < 8; index5++)
    	{
    		result += (layer5[index5] >= 0.5)? 1 : 0;
    	}
    	printf("returning result as %d \n", result);
    	return result;
    }
    
    void newGeneration()
    {
    	int weight = sum();
    	int current[DNA];
    	int random;
    	int count;
    	float *play1;
    	float *play2;
    	for(int player = 0; player < POPSIZE-1; player++)
    	{
    		play1 = genes[getIndex(rand() % weight)];
    		play2 = genes[getIndex(rand() % weight)];
    		random = (((float) rand() / (float) RAND_MAX)*DNA);
    		count = 0;
    		while(count <= random)
    		{
    			tempGenes[player][count]= ( ((float) rand() / (float) RAND_MAX) >= mutationRate)? play1[count]: (((float) rand()) / (float) RAND_MAX)*2 -1;
    		}
    		while(count < DNA)
    		{
    			tempGenes[player][count]= ( ((float) rand() / (float) RAND_MAX) >= mutationRate)? play2[count]: (((float) rand()) / (float) RAND_MAX)*2 -1;
    		}
    	}
    	tempGenes[POPSIZE-1] = genes[maxOfFitnessIndex()];
    	for (int player = 0; player < POPSIZE; player++)
    	{
    		genes[player] = tempGenes[player];
    	}
    }
    
    int sum()
    {
    	int sum = 0;
    	for (int i = 0; i < POPSIZE; i++)
    	{
    		sum += fitSum[i];
    	}
    	return sum;
    }
    
    int getIndex(int top)
    {
    	int index = 0;
    	while(top>=0)
    	{
    		top -= fitSum[index];
    		index += 1;
    	}
    	index -= 1;
    	return index;
    }
  18. #10
  19. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,625
    Rep Power
    4247
    Ran this through a debugger and I found the cause of your dump:
    In line 85, we have:
    Code:
    		move = moveTTT(player1,1);
    and on line 97 we have:
    Code:
    		move = moveTTT(moveNN(player2),2);
    This is where it is core dumping. And the reason it core dumps is because moveNN() is returning an int value, which is getting passed to moveTTT as a pointer to an int array (which explains your core dump). You should probably remove the call to moveNN() in line 97

    By the way, it would be useful to turn on your warnings and add prototypes for all your function calls. That would have saved you a lot of grief, as the warnings clearly point to the call as suspicious (passing an int where it is expecting an int array)

    Comments on this post

    • hovestar agrees : Thank you so much for the fix, it was giving me a ton of grief! If I could give Rep I would.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    13
    Rep Power
    0
    Thank you so much!! I can't wait to try this! my hope is it will produce the "perfect" tic-tac-toe player.

IMN logo majestic logo threadwatch logo seochat tools logo