I have developed a snake game in C and have used malloc is multiple cases. I am a beginner in C, so I think that I have freed all heap memory, but it still does show a leak when i use valgrind. These are the methods in my snakeGame.c file that use memory on heap. Please help me figure out the leak. Thanks in advance!
LinkedList* list; char ** charArray;
int rows, columns, foodX, foodY, goal;
int currentScore=0;
int biteCount=0;
void initializeData(char pFilename[], int foodGoal)
{
int i;
list=createLinkedList();
readFile(pFilename);
goal=foodGoal;
/ *Initialising the 2-D malloc'd array */
charArray=(char**)malloc(rows*sizeof(char*));
for(i=0;i<columns;i++)
charArray[i]=(char*)malloc(columns*sizeof(char*));
}
void readFile(char fileName[])
{
FILE* file=fopen(fileName, "r");
if(file==NULL)
{
perror("Error opening file.");
}
else
{
char line[255];
while (fgets(line,255,file))
{
splitLine(line, 255);
fgets(line,255,file);
splitLine(line, 255);
}
}
fclose(file);
free(file);
file=NULL;
}
void splitLine(char line[], int length)
{
int rowLength, columnLength;
int rowPosition, columnPosition;
char character;
if(sscanf(line, "%d %d %c", &rowPosition, &columnPosition, &character)==3)
{
SnakePart* snakePart=(SnakePart*)malloc(sizeof(SnakePart));
(*snakePart).xPosition=rowPosition+1;
(*snakePart).yPosition=columnPosition+1;
(*snakePart).character=character;
insertFirst(list,(void*) snakePart);
free(snakePart);
snakePart=NULL;
}
else if(sscanf(line, "%d %d", &rowLength, &columnLength)==2)
{
rows=rowLength+2;
columns=columnLength+2;
}
}
int contains(int rowNumber, int columnNumber)
{
LinkedListNode* currentNode=(*list).tail;
SnakePart* tempSnakePart;
int doesContain=0;
while((currentNode)!=NULL)
{
tempSnakePart=(SnakePart*)(currentNode->data);
if(tempSnakePart->xPosition==rowNumber && tempSnakePart->yPosition==columnNumber)
doesContain=1;
currentNode=currentNode->previous;
}
free(tempSnakePart);
tempSnakePart=NULL;
free(currentNode);
currentNode=NULL;
return doesContain;
}
char getCharacterFromList(int rowNumber, int columnNumber)
{
char returnChar=" ";
LinkedListNode* currentNode=((*list).tail);
SnakePart* currentSnakePart;
while ((currentNode)!=NULL)
{
currentSnakePart=(SnakePart*)(currentNode->data);
if(currentSnakePart->xPosition==rowNumber && currentSnakePart->yPosition==columnNumber)
returnChar=currentSnakePart->character;
currentNode=currentNode->previous;
}
free(currentSnakePart);
currentSnakePart=NULL;
free(currentNode);
currentNode=NULL;
return returnChar;
}
int move(char inputChar)
{
SnakePart* tempSnakePart=(SnakePart*)((*list).head->data);
int returnVal=0;
LinkedListNode* headNode=(*list).head;
LinkedListNode* tailNode=(*list).tail;
SnakePart* headSnakePart=(SnakePart*)(headNode->data);
SnakePart* tailSnakePart=(SnakePart*)(tailNode->data);
if(inputChar=='d'&& (*tempSnakePart).yPosition<columns-2)
{
if(hasSnakeEatenBody(inputChar)==1)
returnVal=1;
(*tempSnakePart).yPosition+=1;
shuffleList(inputChar);
}
else if(inputChar=='a' && (*tempSnakePart).yPosition>1)
{
if(hasSnakeEatenBody(inputChar)==1)
returnVal=1;
(*tempSnakePart).yPosition-=1;
shuffleList(inputChar);
}
else if(inputChar=='s' && (*tempSnakePart).xPosition<rows-2)
{
if(hasSnakeEatenBody(inputChar)==1)
returnVal=1;
(*tempSnakePart).xPosition+=1;
shuffleList(inputChar);
}
else if(inputChar=='w' && (*tempSnakePart).xPosition>1)
{
if(hasSnakeEatenBody(inputChar)==1)
returnVal=1;
(*tempSnakePart).xPosition-=1;
shuffleList(inputChar);
}
else
{
printf("Snake cannot move out of mapn");
}
headSnakePart->character=chooseHead(inputChar);
tailSnakePart->character="#";
if(returnVal==1)
{
printf("Game over! You lose :(n");
}
free(tempSnakePart);
tempSnakePart=NULL;
free(headNode);
headNode=NULL;
free(tailNode);
tailNode=NULL;
free(headSnakePart);
headSnakePart=NULL;
free(tailSnakePart);
tailSnakePart=NULL;
return returnVal;
}
int hasSnakeEatenBody(char pInput)
{
SnakePart* tempSnakePart=(SnakePart*)((*list).head->data);
int x,y;
int returnVal=0;
x=(tempSnakePart->xPosition);
y=(tempSnakePart->yPosition);
if(pInput=='d')
{
if(charArray[x][y+1]!=' ' && charArray[x][y+1]!='@' && charArray[x][y+1]!='*')
returnVal=1;
}
else if(pInput=='a')
{
if(charArray[x][y-1]!=' ' && charArray[x][y-1]!='@' && charArray[x][y-1]!='*')
returnVal=1;
}
else if(pInput=='w')
{
if(charArray[x-1][y]!=' ' && charArray[x-1][y]!='@' && charArray[x-1][y]!='*')
returnVal=1;
}
else if(pInput=='s')
{
if(charArray[x+1][y]!=' ' && charArray[x+1][y]!='@' && charArray[x+1][y]!='*')
returnVal=1;
}
free(tempSnakePart);
tempSnakePart=NULL;
return returnVal;
}
void shuffleList(char input)
{
LinkedListNode* currentNode=(*list).tail;
LinkedListNode* tempNode=(*currentNode).previous;
LinkedListNode* headNode=(*list).head;
SnakePart* tempSnakeCurrent=(SnakePart*)(currentNode->data);
SnakePart* tempSnakePrevious=(SnakePart*)(tempNode->data);
SnakePart* headSnakePart=(SnakePart*)(headNode->data);
headSnakePart->character=chooseBody(input);
while ((*tempNode).previous!=NULL)
{
tempNode=(*currentNode).previous;
tempSnakeCurrent=(SnakePart*)(currentNode->data);
tempSnakePrevious=(SnakePart*)(tempNode->data);
tempSnakeCurrent->xPosition=tempSnakePrevious->xPosition;
tempSnakeCurrent->yPosition=tempSnakePrevious->yPosition;
tempSnakeCurrent->character=tempSnakePrevious->character;
currentNode=(*currentNode).previous;
}
free(tempNode);
tempNode=NULL;
free(headNode);
headNode=NULL;
free(tempSnakeCurrent);
tempSnakeCurrent=NULL;
free(tempSnakePrevious);
tempSnakePrevious=NULL;
free(headSnakePart);
headSnakePart=NULL;
}
void hasSnakeEatenFood()
{
SnakePart* snakeHead=(SnakePart*)((*list).head->data);
if(foodX==(*snakeHead).xPosition && foodY==(*snakeHead).yPosition)
{
generateFood();
incrementSnakeLength();
currentScore++;
}
else
{
charArray[foodX][foodY]='@';
}
free(snakeHead);
snakeHead=NULL;
}
void incrementSnakeLength()
{
SnakePart* newSnakePart=(SnakePart*)malloc(sizeof(SnakePart));
LinkedListNode* tempNode=(*list).tail;
SnakePart* tempSnakePart=(SnakePart*)((*tempNode).data);
newSnakePart->xPosition=tempSnakePart->xPosition;
newSnakePart->yPosition=tempSnakePart->yPosition-1;
newSnakePart->character=tempSnakePart->character;
tempSnakePart->character="#";
insertLast(list, (void*)newSnakePart);
free(newSnakePart);
newSnakePart=NULL;
free(tempSnakePart);
tempSnakePart=NULL;
free(tempNode);
tempNode=NULL;
}
void freeSnake()
{
LinkedListNode* node=(*list).head;
while (node!=NULL)
{
SnakePart* tempSnakePart=(SnakePart*)node->data;
free(tempSnakePart);
tempSnakePart=NULL;
node=node->next;
}
free(node);
node=NULL;
}
void closeMemoryLeaks()
{
int i;
freeSnake();
freeLinkedList(list);
for(i=0;i<rows;i++)
{
free(charArray[i]);
charArray[i]=NULL;
}
free(list->head);
free(list);
free(charArray);
charArray=NULL;
}
This is the method in my linkedList file to free memory:
void freeLinkedList(LinkedList* list)
{
LinkedListNode* node, *nextNode;
node=(*list).head;
while(node!=NULL)
{
printf("freedn");
nextNode=(*node).next;
free((*node).data);
free(node);
node=nextNode;
}
free(node);
node=NULL;
free(nextNode);
nextNode=NULL;
free(list);
list=NULL;
}