-I'm pretty bad at managing to correctly free up all memory. Could someone please help me out? I freed pList, but I'm not sure what else I need to free up and how. I use valgrind to check for memory leaks, and it seems like I still have quite a lot. Thank you for your time!Code:#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define FLUSH while (getchar() != '\n') // Global Declarations typedef int KEY_TYPE; typedef struct { KEY_TYPE key; char modifier; char *name; float gpa; } DATA; typedef struct nodeTag { DATA data; struct nodeTag* link; } NODE; // Function Declarations NODE* insertNode (NODE* pList, NODE* pPre, DATA item); bool searchList (NODE* pList, NODE** pPre, NODE** pCur, DATA* item); void printList (NODE* pList); NODE* buildList (char* fileID); bool getData (FILE* fpData, DATA* pData); void printListByGpa (NODE* pList, float target); void saveHiGpa (NODE* pList); float HIGPA = 0.0; // Header file to include functions (Not in text) //#include "P15-LIST.H" int main (void) { // Local Declarations NODE* pList; NODE* pPre; NODE* pCur; DATA data; double avrg; char more; // Statements printf("Begin list test driver\n\n"); // Build List pList = buildList("gpaDS.txt"); if (!pList) { printf("Error building chron file\a\n"); exit (100); } printList (pList); saveHiGpa (pList); while(1) { printf("\nPrint by gpa tests.\n"); printf("Enter target score: "); while (scanf ("%f", &data.gpa) != 1) { FLUSH; printf("Invalid number, please re-enter: "); } if(data.gpa==-1){ printf("Exiting...\n"); break; } printListByGpa (pList, data.gpa); } printf("\nTests complete.\n"); return 0; } // main /* ==================== insertNode ==================== This function inserts a single node into a linear list. Pre pList is pointer to the list; may be null pPre points to new node.s predecessor item contains data to be inserted Post returns the head pointer */ NODE* insertNode (NODE* pList, NODE* pPre, DATA item) { // Local Declarations NODE* pNew; // Statements if (!(pNew = (NODE*)malloc(sizeof(NODE)))) printf("\aMemory overflow in insert\n"), exit (100); pNew->data = item; if (pPre == NULL) { // Inserting before first node or to empty list pNew->link = pList; pList = pNew; } // if pPre else { // Inserting in middle or at end pNew->link = pPre->link; pPre->link = pNew; } // else return pList; } // insertNode /* ==================== searchList ==================== Given key value, finds the location of a node Pre pList points to a head node pPre points to variable to receive pred pCur points to variable for current node target is a pointer to the data with key being sought Post pCur points to first node with >= key -or- null if target > key of last node pPre points to largest node < than key -or- null if target < key of first node function returns true if found false if not found */ bool searchList (NODE* pList, NODE** pPre, NODE** pCur, DATA* target) { // Local Declarations bool found = false; // Statements *pPre = NULL; *pCur = pList; // start the search from beginning while (*pCur != NULL && target->key > (*pCur)->data.key ) { *pPre = *pCur; *pCur = (*pCur)->link; } // while while (*pCur != NULL && target->key == (*pCur)->data.key && target->modifier>(*pCur)->data.modifier) { *pPre = *pCur; *pCur = (*pCur)->link; } if (*pCur != NULL && target->key == (*pCur)->data.key && target->modifier==(*pCur)->data.modifier) found = true; return found; } // searchList /* Traverse and print a linear list. Pre pList is a valid linear list Post List has been printed */ void printList (NODE* pList) { // Local Declarations NODE* pWalker; // Statements pWalker = pList; printf("List contains:\n"); printf(" PIN Name GPA\n"); printf(" === ============ ======= \n"); while (pWalker) { printf("%3d%c %s %.1f\n", pWalker->data.key,pWalker->data.modifier,pWalker->data.name,pWalker->data.gpa); pWalker = pWalker->link; } // while printf("\n"); return; } // printList /* Traverse and print a linear list. Pre pList is a valid linear list Post List has been printed */ void saveHiGpa (NODE* pList) { // Local Declarations NODE* pWalker; char* best_students_file="best_students.txt"; FILE* foutData; // Statements pWalker = pList; foutData=fopen(best_students_file,"w"); if(!foutData){ printf("Error opening file %s\a\n", best_students_file); exit (210); } while (pWalker) { if(pWalker->data.gpa==HIGPA){ fprintf(foutData,"%3d%c %s %.1f\n", pWalker->data.key,pWalker->data.modifier,pWalker->data.name,pWalker->data.gpa); } pWalker = pWalker->link; } // while fclose(foutData); return; } // printList /* Traverse and print a linear list. Pre pList is a valid linear list Post List has been printed */ void printListByGpa (NODE* pList, float target) { // Local Declarations NODE* pWalker; // Statements pWalker = pList; printf("List contains:\n"); while (pWalker) { if(pWalker->data.gpa>=target){ printf("%3d%c %s %.1f\n", pWalker->data.key,pWalker->data.modifier,pWalker->data.name,pWalker->data.gpa); } pWalker = pWalker->link; } // while printf("\n"); return; } // printList /* ==================== buildList ==================== This program builds a key-sequenced linear list. Pre fileID is file that contains data for list Post list built returns pointer to head of list */ NODE* buildList (char* fileID) { // Local Declarations DATA data; NODE* pList; NODE* pPre; NODE* pCur; FILE* fpData; // Statements pList = NULL; fpData = fopen(fileID, "r"); if (!fpData) { printf("Error opening file %s\a\n", fileID); exit (210); } // if open fail while (getData (fpData, &data)) { if(HIGPA==0.0){ HIGPA=data.gpa; } else { if(HIGPA<data.gpa){ HIGPA=data.gpa; } } // Determine insert position searchList (pList, &pPre, &pCur, &data); pList = insertNode(pList, pPre, data); } // while return pList; } // buildList /* ==================== getData ==================== Reads data from file. Pre fpData is an open file pData is pointer to input structure Post data read returns success/failure */ bool getData (FILE* fpData, DATA* pData) { // Local Definitions char *ioResult; char buffer[100]; pData->name = (char*) malloc(100*sizeof(char)); // Statements ioResult = fgets(buffer, 100, fpData); if(ioResult){ sscanf(buffer, "%d%c %[^;]%*c %f", &(pData->key), &(pData->modifier), pData->name, &(pData->gpa)); } return ioResult; } // getData void destroyList(NODE* pList, DATA data) { free(pList); return; }