Discuss Segmentation fault in the C Programming forum on Dev Shed. Segmentation fault C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
Posts: 13
Time spent in forums: 3 h 44 m 21 sec
Reputation 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?
Posts: 6,141
Time spent in forums: 2 Months 2 Weeks 3 Days 23 h 52 m 21 sec
Reputation Power: 1974
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.
Posts: 3,840
Time spent in forums: 2 Months 3 Weeks 2 Days 19 h 25 m 12 sec
Reputation Power: 1774
> 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.
Posts: 13
Time spent in forums: 3 h 44 m 21 sec
Reputation 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.
Posts: 4,808
Time spent in forums: 1 Month 2 Days 17 h 43 m 11 sec
Reputation Power: 1800
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.
Posts: 3,840
Time spent in forums: 2 Months 3 Weeks 2 Days 19 h 25 m 12 sec
Reputation Power: 1774
> 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.
Location: Woodland Hills, Los Angeles County, California, USA
Posts: 9,390
Time spent in forums: 1 Month 4 Weeks 1 Day 22 h 32 m 40 sec
Reputation Power: 4080
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)
__________________ 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