2

just revising C here. I just ran valgrind and it turns out i have memory leaks in my program, even though i free the memory i allocate. What am i missing?

stack.c:

#include <stdlib.h>
#include <stdio.h>
#include "stack.h"

struct node {
  int element;
  Node *next;
};

struct stack {
  Node *tos;
};

Stack *stack_create() {
  Stack *S;
  if ((S = (Stack *)malloc(sizeof(Stack))) != NULL)
      S->tos = NULL;
  return S;
}

void stack_destroy(Stack *S) {
  Node *temp = S->tos;
  while (S->tos != NULL) {
    temp = S->tos;
    free(S->tos);
    S->tos = temp->next;
  }
  free(S);
}

void push(Stack *S, int element) {
  Node *N;
  if ((N = (Node *)malloc(sizeof(Node))) != NULL) {
    N->element = element;
    N->next = (S->tos == NULL) ? NULL : S->tos;
    S->tos = N;
  }
}

int pop(Stack *S) {
  Node *tos = S->tos;
  S->tos = tos->next;  
  return (int) tos->element;
}

int peek(Stack *S) {
  return (int) S->tos->element;
}

void to_string(Stack *S) {
  Node *cursor = S->tos;
  while (cursor != NULL) {
    printf("[%d] ", cursor->element);
    cursor = cursor->next;
  }
  printf("\n");
}


int main() 
{
  Stack *S;

  S = stack_create();

  push(S, 5);
  push(S, 6);
  push(S, 4);
  push(S, -55);

  to_string(S);

  printf("Pop %d\n", pop(S));
  printf("Pop %d\n", pop(S));

  to_string(S);

  stack_destroy(S);

  return 0;  
}

enter image description here

chuckfinley
  • 2,577
  • 10
  • 32
  • 42

3 Answers3

2

the actual problem is your Pop kills the node, but it doesn't free it

Node* node_destroy(Node* n)

    Node* next;
    if(n == NULL) return NULL;
    next = n->next;
    free(n);
    return next;
}


int stack_pop(Stack *s) {
      int element;
      if(s == NULL || s->tos == NULL) return 0;  // no really good result you can give
      element = s->tos->element;    
      s->tos = node_destroy(s->tos);
      return element;
    }

then you can do

void stack_destroy(Stack *S) {
  while (S->tos != NULL) {
    s->tos = node_destroy(s->tos);
  }
  free(S);
}
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
0

The problem is in your destroy method. You free S->tos which temp refers to. Then you use temp->next.

set temp to S->tos->next.

KooKoo
  • 451
  • 3
  • 20
0

The problem is with your destory:

void stack_destroy(Stack *S) {
  Node *temp = S->tos;
  while (S->tos != NULL) {
    temp = S->tos;
    free(S->tos);
    S->tos = temp->next;
  }
  free(S);
}

Temp is pointing to S->tos from:

temp = S->tos;

But then you immediately free it after:

free(S->tos);

Then when you call the temp->next; temp is already freed.

Try this:

void stack_destroy(Stack *S) {
  Node *temp; //Also, no need to assign here from the original (you assign to it immediately within the while)
  while (S->tos != NULL) {
    temp = S->tos->next; //You need to get the pointer to node "next" before you free S->tos
    free(S->tos);
    S->tos = temp;
  }
  free(S);
}

EDIT1: Per Keith Nicholas - See here for his elegant solution

Pop also does not free the node you extract the element from:

old:

int pop(Stack *S) {
  Node *tos = S->tos;
  S->tos = tos->next;  
  return (int) tos->element;
}

new:

int pop(Stack *S) {
  Node *tos = S->tos;
  int element = tos->element;
  S->tos = tos->next;  
  free(tos);
  return element;
}
Community
  • 1
  • 1
MrHappyAsthma
  • 6,332
  • 9
  • 48
  • 78