2014-02-18 125 views
2

这里只是修改C.我只是跑了valgrind,事实证明我的程序中有内存泄漏,即使我释放了我分配的内存。我错过了什么?堆栈在C:为什么我有内存泄漏?

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

+0

也许它太明显了,但我敢确定你只需要改变你的“stack_destroy”。在保存“S-> tos-> next”之前,您可以释放“S-> tos”。 – MrHappyAsthma

+0

你为什么不包含valgrind输出? – hyde

+1

在stack_destroy中,而不是temp调用它Node * next;那么next = S-> tos-> next;那么s-> tos = next;这样你就不会引用free'd内存,尽管这不是你的问题 –

回答

0

的问题是在你的destroy方法。您可以免费获得S->tos哪些温度指的是。然后你使用temp->next

设置温度为S->tos->next

0

问题是与你的毁灭:

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); 
} 

温度从指向S->tos

temp = S->tos; 

但你马上免费之后:

free(S->tos); 

然后,当你请拨打temp->next;温度已经释放。

试试这个:

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:每Keith Nicholas - See here for his elegant solution

流行也不会释放你从提取的元素节点:

老:

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

新:

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

错误,您的代码错误 –

+1

现在其更好:) –

+0

我复制并粘贴了错误的东西:P – MrHappyAsthma

2

实际的问题是你的流行杀死节点,但它不释放它

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; 
    } 

那么你可以做

void stack_destroy(Stack *S) { 
    while (S->tos != NULL) { 
    s->tos = node_destroy(s->tos); 
    } 
    free(S); 
} 
+1

噢,真的,我只是取消引用它,那就是 - 它 - 丢失了 – chuckfinley

+1

你还需要考虑提供一个'is_stack_empty'函数,因为如果弹出一个空栈 –