I am working on a C homework, and I am finding it pretty confusing to detect what memory was not de-allocated.
I been trying to place free() function in different locations on my code just to check whether would it work or not but none of the trys has paid off yet.
this is the struct and the functions used for it; all the functions below are inside one file called state.c - stateAdd calls stateNodeCreate -
typedef struct node_t {
int id;
const char* name;
const char* song;
Set votes;
Set grades;
int top_grade;
}*StateNode;
void stateNodeDestroy(StateNode node) {
if(node == NULL) {
return;
}
if(node->votes) {
setDestroy(node->votes);
}
if(node->grades) {
setDestroy(node->grades);
}
free(node);
}
static StateNode stateNodeCreate(int id,const char* name,const char* song) {
StateNode state = (StateNode)malloc(sizeof(*state));
if(state == NULL) {
return NULL;
}
state->id = id;
state->name = name;
state->song = song;
state->top_grade = -1;
Set votes_set = setCreate(copyVoteElement,
freeVoteElement, compareVotes);
if(votes_set == NULL) {
free(state);
return NULL;
}
state->votes = votes_set;
Set grades_set = setCreate(copyGradeElement,
freeGradeElement, compareGrades);
if(grades_set == NULL) {
stateNodeDestroy(state);
setDestroy(grades_set);
return NULL;
}
state->grades = grades_set;
return state;
}
stateResult StateAdd(Set states, int stateId, const char* stateName, const char* songName) {
if (states == NULL) {
return STATE_NULL_ARGUMENT;
}
if(stateId < 0 ) {
return STATE_INVALID_ID;
}
if(!IsValidName(stateName) || !IsValidName(songName)) {
return STATE_INVALID_NAME;
}
StateNode state_exist = findState(states,stateId);
if(state_exist != NULL) {
return STATE_STATE_ALREADY_EXIST;
}
free(state_exist);
StateNode new_state = stateNodeCreate(stateId,stateName,songName);
if(new_state == NULL) {
return STATE_OUT_OF_MEMORY;
}
if(setAdd(states,new_state) == SET_OUT_OF_MEMORY) {
stateNodeDestroy(new_state);
setDestroy(states);
return STATE_OUT_OF_MEMORY;
}
return STATE_SUCCESS;
}
setDestroys destroys an already made set using setCreate and setCreate has function pointers as parameters and it uses these functions to copy/free data from the sets (an ADT)
Below are functions from another file: eurovision.c : eurovisionAddState calls stateAdd that exists in state.c file -
typedef struct eurovision_t {
Set states;
Set judges;
} *Eurovision;
EurovisionResult eurovisionAddState(Eurovision eurovision, int stateId, const char *stateName, const char *songName) {
stateResult result = StateAdd(eurovision->states, stateId, stateName, songName);
if (result == STATE_NULL_ARGUMENT) {
return EUROVISION_NULL_ARGUMENT;
}
if (result == STATE_OUT_OF_MEMORY) {
//setDestroy(eurovision->judges);
eurovisionDestroy(eurovision);
return EUROVISION_OUT_OF_MEMORY;
}
if (result == STATE_INVALID_ID) {
return EUROVISION_INVALID_ID;
}
if (result == STATE_STATE_ALREADY_EXIST) {
return EUROVISION_STATE_ALREADY_EXIST;
}
if (result == STATE_INVALID_NAME) {
return EUROVISION_INVALID_NAME;
}
return EUROVISION_SUCCESS;
}
void eurovisionDestroy(Eurovision eurovision) {
if (eurovision == NULL) {
return;
}
if(eurovision->judges != NULL) {
setDestroy(eurovision->judges);
}
if(eurovision->states != NULL) {
setDestroy(eurovision->states);
}
free(eurovision);
}
eurovisionDestroy clears the Sets inside of the parameter eurovision and frees the eurovision element. And the last part is this function that exist in test.c: The function testAddState calls the function eurovisionAddState that exists in eurovision.c file -
bool testAddState() {
Eurovision eurovision = setupEurovision();
CHECK(eurovisionAddState(eurovision, 0, "israel", "home"), EUROVISION_SUCCESS);
//CHECK(eurovisionAddState(eurovision, 1, "malta", "chameleon"), EUROVISION_SUCCESS);
//CHECK(eurovisionAddState(eurovision, 0, "croatia", "the dream"), EUROVISION_STATE_ALREADY_EXIST);
//CHECK(eurovisionAddState(eurovision, 0, "israel", "home"), EUROVISION_STATE_ALREADY_EXIST);
//CHECK(eurovisionAddState(eurovision, -1, "croatia", "the dream"), EUROVISION_INVALID_ID);
eurovisionDestroy(eurovision);
return true;
}
after all that, when using valgrind to detect memory leaks, It still shows that in this piece of code, there are memory leaks. Valgrind says the following:
48 bytes in 1 blocks are definitely lost in loss record 1 of 1
==10451== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==10451== by 0x402A71: stateNodeCreate (state.c:124)
==10451== by 0x402DA9: StateAdd (state.c:236)
==10451== by 0x40082D: eurovisionAddState (eurovision.c:49)
==10451== by 0x4015E9: testAddState (eurovisionTests.c:169)
==10451== by 0x4027CE: main (eurovisionTestsMain.c:15)
This is not the whole code, I am very positive that the rest works just fine to not cause any memory leaks to this piece of code. Any ideas?