2014-02-18 2 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

in stack_destroy, 임시 호출 대신 Node * next; then next = S-> tos-> next; then s-> tos = next; 그런 식으로 당신은 free'd 메모리를 참조하지 않습니다. 이것은 당신의 문제가 아닙니다. –

답변

0

문제는 당신 파괴하는 방법입니다. 임시 직원이 말하는 S->tos 무료입니다. 그런 다음 temp->next을 사용합니다.

설정 온도는 S->tos->next입니다.

0

문제는 32 파괴 함께 :

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' 함수를 제공하는 것에 대해 생각할 필요가 있습니다 –

관련 문제