0

Struggling to learn how malloc and free work, but I thought that I might of had it right. I am calling a deleteList() at the end of my test file which should free all the memory, but when I use valgrind it states I still have allocated memory active. If anyone knows how I might resolve this, it would be great.

Testing source file:

#include "stdlib.h"
#include "string.h"
#include "linked_list.h"

int main(int argc, char* argv[]){
  PersonalInfo *head = NULL;

  printList(head);

  insertToList(&head, 2, "Mike", "Pealow");
  printList(head);

  deleteList(&head);

  return 0;
}

Prototype file:

#define NAME_LENGTH 32

typedef struct personalInfo {
  struct personalInfo *next;
  unsigned int id;    
  char firstName[NAME_LENGTH];
  char familyName[NAME_LENGTH];
} PersonalInfo;

PersonalInfo *insertToList(PersonalInfo **head, unsigned int id, char *firstName, char *familyName);
void printList(PersonalInfo *head);
void deleteList(PersonalInfo **head);

Source file:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "linked_list.h"

PersonalInfo *insertToList(PersonalInfo **head, unsigned int id, char *firstName, char *familyName){
  PersonalInfo *p = (PersonalInfo*)malloc(sizeof(PersonalInfo));
  strcpy(p->firstName, firstName);
  strcpy(p->familyName, familyName);
  p->id = id;
  p->next = NULL;
  if(*head!=NULL && p!=NULL){
    p->next = *head;
    return p;
  }
  else{
    printf("Head is null; create new head? (y/n)");
    char scChar;
    scanf("%c", &scChar);
    if(scChar=='y'){
      head = &p;
      return p;
    }
    else if(scChar=='n'){
      printf("Exiting");
      free(p);
      p=NULL;
      return NULL;
    }
    else{
      printf("Invalid input, exiting");
      free(p);
      p=NULL;
      return NULL;
    }
  }
}


void printNode(PersonalInfo *node){
  printf("%s %s %d", node->firstName, node->familyName, node->id);
}

void deleteList(PersonalInfo **head){
  if(*head==NULL)
    printf("List is empty\n");
  PersonalInfo *next, *currNode = *head;
  while(currNode!=NULL){
    next = currNode->next;
    free(currNode);
    currNode = next;
  }
  currNode = NULL;
}
Sythe
  • 143
  • 1
  • 1
  • 9
  • Did you compile with `gcc -Wall -Wextra -g` ? Then `valgrind` should give interesting messages. BTW you should end your `printf` format control strings with `\n` or else use `fflush(NULL);` – Basile Starynkevitch Mar 11 '15 at 14:01
  • What are you trying to do with this `if(&head!=NULL && &p!=NULL)` ?? This will always return true, as p and head are local variables, their address will never be NULL – Bregalad Mar 11 '15 at 14:04
  • Also, `head` is already a pointer, there is no need to pass a pointer to it, just pass it directly. – Bregalad Mar 11 '15 at 14:06
  • There is that indeed. It would be simpler to just pass `head` and not `&head` – emvee Mar 11 '15 at 14:07
  • I realized this afterwards, earlier when I was writing this, gcc would give warnings about using *head or head but not &head, even though I knew it would probably be wrong. I've edited the post – Sythe Mar 11 '15 at 14:29
  • you should check `malloc` return value and shouldn't cast it: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Jason Hu Mar 11 '15 at 14:36
  • You edit had introduced another typo: `while(*!=NULL)` makes no sense. I believe you want `while (currNode != NULL)`. – Adrian McCarthy Mar 11 '15 at 16:19

3 Answers3

1

I'm surprised your program terminates at all.

First off:

void deleteList(PersonalInfo **head){
  if(&head==NULL)

should read:

if( *head==NULL )

because the address of the pointer-to-pointer is always non-NULL so your test always fails.

Next:

  printf("List is empty\n");
  PersonalInfo *next, *currNode = *head;
  while(&currNode!=NULL){

Same here: &currNode is always non-NULL so this condition should never be false, i.e. your program should not terminate. You need to test in stead:

 while( currNode!=NULL )
emvee
  • 4,371
  • 23
  • 23
0

I see that your insertIntoList function adds a new node to the beginning of the list but you never change the reference to the first note(the head pointer). So when you free your list you only free the last node.

In your main() function try calling head = insertToList(&head, 2, "Mike", "Pealow"); or if you insist on having a double pointer for the first argument of insertIntoList after p->next = *head; add a *head = p

mihair
  • 11
  • 2
0

Found out where the issue was, I was allocating memory from the head without removing it, so when the program ran, it would still count head for memory allocation.

In the testing source file:

PersonalInfo *head = NULL;
Sythe
  • 143
  • 1
  • 1
  • 9