2013-06-16 7 views
0

여기서 스택의 요소를 삭제할 수 있는지 간단한 테스트를했습니다.C에서 스택의 요소 삭제

// This program test whether an object is dynamically allocated and passed as a parameter to a function , \ 
//free()ed in that function , then would it really get free()ed or still existing 

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

typedef struct node 
{ 
    int data ; 
    struct node *next; 
} node ; 

void deleteElement(int *p) 
{ 

    free(p); 
} 

void deleteNode(node *node) 
{ 
    free(node); 
} 

int main() 
{ 
    int i = 10 ; 
    int *p = &i ; 

    node *parent = (node *)malloc(sizeof(node)); 
    parent->data = 10; 

    node *child = (node *)malloc(sizeof(node)); 
    parent->next = child ; 

    deleteElement(p); 
    printf("\np : %d",*p); 

    deleteNode(parent); 
    printf("\nparent node: %d",parent->data); 
    printf("\nchild node : %d",child->data); 
    return 0 ; 
} 

는하지만 나무의 삭제를 구현하면서

[email protected]:~/Code::Blocks/ProgrammingTests$ ./a.out 
*** glibc detected *** ./a.out: free(): invalid pointer: 0x00007fff9e9fa284 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f34da65cb96] 
./a.out[0x4005c4] 
./a.out[0x400635] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f34da5ff76d] 
./a.out[0x4004c9] 
======= Memory map: ======== 
00400000-00401000 r-xp 00000000 07:00 383254        /home/codejack/Code::Blocks/ProgrammingTests/a.out 
00600000-00601000 r--p 00000000 07:00 383254        /home/codejack/Code::Blocks/ProgrammingTests/a.out 
00601000-00602000 rw-p 00001000 07:00 383254        /home/codejack/Code::Blocks/ProgrammingTests/a.out 
0190a000-0192b000 rw-p 00000000 00:00 0         [heap] 
7f34da3c8000-7f34da3dd000 r-xp 00000000 07:00 197806      /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f34da3dd000-7f34da5dc000 ---p 00015000 07:00 197806      /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f34da5dc000-7f34da5dd000 r--p 00014000 07:00 197806      /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f34da5dd000-7f34da5de000 rw-p 00015000 07:00 197806      /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f34da5de000-7f34da793000 r-xp 00000000 07:00 700468      /lib/x86_64-linux-gnu/libc-2.15.so 
7f34da793000-7f34da992000 ---p 001b5000 07:00 700468      /lib/x86_64-linux-gnu/libc-2.15.so 
7f34da992000-7f34da996000 r--p 001b4000 07:00 700468      /lib/x86_64-linux-gnu/libc-2.15.so 
7f34da996000-7f34da998000 rw-p 001b8000 07:00 700468      /lib/x86_64-linux-gnu/libc-2.15.so 
7f34da998000-7f34da99d000 rw-p 00000000 00:00 0 
7f34da99d000-7f34da9bf000 r-xp 00000000 07:00 700456      /lib/x86_64-linux-gnu/ld-2.15.so 
7f34daba5000-7f34daba8000 rw-p 00000000 00:00 0 
7f34dabbc000-7f34dabbf000 rw-p 00000000 00:00 0 
7f34dabbf000-7f34dabc0000 r--p 00022000 07:00 700456      /lib/x86_64-linux-gnu/ld-2.15.so 
7f34dabc0000-7f34dabc2000 rw-p 00023000 07:00 700456      /lib/x86_64-linux-gnu/ld-2.15.so 
7fff9e9db000-7fff9e9fc000 rw-p 00000000 00:00 0       [stack] 
7fff9e9ff000-7fff9ea00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
Aborted (core dumped) 

는 사실 내가 갇혀 있던 다음과 같은 오류가 발생합니다. free()을 사용하여 리프 노드를 삭제했으며 이제 부모 노드가 리프 노드가되어 재귀를 사용하여 해당 노드를 삭제합니다. 그러나 리프 노드가 실제로 삭제되지 않는 문제는 여전히 존재합니다.

void deleteTree(struct node *root) 
{ 
    if(root->left == NULL && root->right == NULL) 
    { 
     free(root); 
    } 
    else 
    { 
     if(root->left != NULL) 
      deleteTree(root->left); 
     if(root->right != NULL) 
      deleteTree(root->right); 
    } 
} 

에만 리프 노드 삭제이 방법을 따르며, 해당 부모 노드가 삭제되지 않았습니다으로 그리고 또한 내가 나무의 삭제에 따르는 방법이다. XCode에서 디버깅을 한 후에 리프 노드가 삭제되지 않았 음을 알았습니다. 아직 남아있었습니다. 그렇다면 왜이 방법은 테스트를 마쳤는데 어떤 오류가 있었습니까?

답변

1

세 가지 명백한 오류 :

(1) deleteElement(p)malloc() 할당되지 않은 포인터에 free()를 호출 끝납니다.

(2)이 코드 :이 삭제 된

deleteNode(parent); 
printf("\nparent node: %d",parent->data); 

참조 변수 parent 후.

(3) deleteTree()에서 자식 노드를 해제 한 후에는 노드가 아닌 노드를 절대로 삭제할 수 없도록 자식 노드에 대한 참조를 유지합니다.

+0

선생님, (2) 출력으로 0을 출력합니다. (3) 참조가 여전히 존재하는 이유는 무엇입니까 ?? – Subbu

+0

(2) 무엇이든 인쇄 할 수 있습니다. 그것은 완전히 정의되지 않았습니다. 실제로, 삭제 된 메모리의 가장 가능성있는 내용은 거기에 있던 내용이므로 코드는 종종 잘못되어도 올바르게 작동합니다. 그것이하는 일을 설명하는 것이 나의 임무는 아닙니다. 그것은 틀렸고, 무엇이든 할 수 있습니다. (3) '왼쪽'및 '오른쪽'포인터는 절대로 지워지지 않습니다. –

1

free() 메모리를 할당 할 수없는 포인터는 사용할 수 없습니다. 귀하의 경우 유효한 스택 메모리를 확보하려고합니다.

void deleteElement(int *p) 
{ 

    free(p); 
} 

int main() 
{ 
    int i = 10 ; 
    int *p = &i ; 
    .... 
    deleteElement(p); 
    ... 
} 


deleteTree() 방법에서 당신은, 그렇지 않으면 무효/해제 된 메모리에 액세스하려고 할 것이라고 ->left 또는 ->right 적절하게 그 free() 에드 후 다시 설정해야합니다.

void deleteTree(struct node *root) 
{ 
    if(root->left == NULL && root->right == NULL) 
    { 
     free(root); 
    } 
    else 
    { 
     if(root->left != NULL) 
     { 
      deleteTree(root->left); 
      root->left = NULL; 
     } 
     if(root->right != NULL) 
     { 
      deleteTree(root->right); 
      root->right = NULL; 
     } 
    } 
} 
+0

포인터가 포인터로 전달되고 스택에있을 때 메모리가 할당되지 않았다는 것을 의미합니까? – Subbu

+0

deleteTree()에서 왜 작동 했습니까 ?? 이 경우 큰 오류가 표시되지 않는 이유는 무엇입니까? – Subbu

+0

@ CodeJack, 네가 메모리를 명시 적으로 할당하지 않은 포인터를 자유롭게해서는 안된다. – Rohan