2013-10-21 3 views
0

그래서 여기 링크 된 목록을 삭제하는 코드가 있습니다.C에서 연결된 목록 삭제하기

void destroy(node *h){ 
    if (h->next!=NULL){ 
     destroy(h->next); 
    } 
    free(h); 
    h=NULL; 

} 

문제 인쇄 여전히 숫자의 무리 출력이다 :

11, 2, 15, 3, 9, // 전 처치를

28495936, 28495968, 28496064, 28496096 , 0, // After Destroy

불행히도 할당 이유 때문에 void destroy(node *h) 매개 변수를 변경할 수 없습니다. while 루프 메서드를 사용해 보았지만 여전히 동일한 결과를 얻습니다. 또한 왼쪽으로 시프트를 시도하고 마지막에서 삭제하지만 마지막 노드를 삭제할 수 없습니다. 사전에

감사합니다. 요청에 따라

--edit은 --- , 여기 당신은 h->next = NULL를 설정해야 인쇄 기능

void print(node* N){ 
     printf("%d, ", N->value); 
    if (N->next) 
     print_set(N->next); 
    if (N == NULL) 
     printf("Empty Set"); 
} 
+1

우리는 당신이 목록을 인쇄하는 데 사용하는 코드를 볼 수 있을까요? – Kaidjin

+0

왜 파괴 한 목록을 인쇄하겠습니까? 할당이 프로토 타입'void destroy (node ​​*)'인 경우'destroy()'를 호출하는 함수에서 포인터를 변경할 수 없기 때문에 포인터가 null이되어 인쇄를 방지 할 수 없습니다. – Eregrith

+0

인쇄용 코드를 추가했습니다. – User49230

답변

1

여기서 문제는 함수에서 h=null이 아무 것도하지 않는다는 것입니다. 로컬 매개 변수를 수정하면 함수 밖에서 아무 효과가 없습니다.

따라서 메모리를 확보하는 것만이 주소를 동일하게 유지합니다. 임의의 메모리 위치를 가리키는 목록이 여전히 존재합니다 (이전과 동일하지만이 메모리 위치의 값은 무작위입니다)

이후에 목록을 인쇄하면 그것을 파괴했는지 ... 왜 다시 인쇄하고 싶습니까?), 임의의 값을 메모리에 인쇄합니다.

이것은 프로그램이 충돌 할 수 있으므로 (할당되지 않은 메모리에 액세스하고 있기 때문에) 문제가됩니다.

이 솔루션은, 불행하게도, 함수의 서명을 변경할 필요

void destroy(node **h){ 
    if ((*h)->next!=NULL){ 
     destroy((*h)->next); 
    } 
    free(*h); 
    *h=NULL; 

} 

당신은, 당신은 이런 식으로 그것을 파괴 후에 NULL 포인터를 설정할 필요가없는 경우 :

void destroy(node *h){ 
    if (h->next!=NULL){ 
     destroy(h->next); 
     h->next=NULL; 
    } 
    free(h); 
} 

및 호출 기능에 :

destroy(myList); 
myList=NULL; 
+0

이 작동합니다. myList = NULL을 메인 메소드에서 설정할 수 있는지 확신 할 수 없습니다 그게 문제 야 .. – User49230

+0

파괴 목록을 사용하지 않도록 다른 방법은 보이지 않는다. 메모리가 해제되었으므로 포인터를 유지하는 것은 쓸모 없으며 NULL을 설정하지 않으면 사용하지 못할 위험이있다. (또는이 질문에서 물어 보았던 것과 비슷한 행동) – Kaidjin

+0

상황에 따라 다른 방법이없는 것 같습니다. 강사에게 물어볼 것입니다. 감사합니다. 도움! :) – User49230

2

입니다. 또한 destroy을 호출 한 후에는 포인터가 해제되어 더 이상 포인터를 사용하지 않도록하십시오. 따라서 항상 destroy(n) 다음에 n = NULL이 있는지 확인하십시오.

더 좋은 방법은 void destroy(node **h)에 서명을 변경 아마, 그래서 코드가된다 :

void destroy(node **h){ 
    if ((*h)->next!=NULL){ 
     destroy(&h->next); 
    } 
    free(*h); 
    *h=NULL; 
} 

그런 다음 당신은 당신이 나중에 포인터를 사용하지 않을 것을 보장한다.

if(N == NULL) return; 
+0

확실하게 도움이되었지만, 내가 인쇄 할 때 하나의 숫자가 인쇄되고있다 : '11, 2, 15, 3, 9, // 11886656 뒤에 ' – User49230

+2

@ PatrickBuhagiar : 여러분의'print' 함수에 실수가 있었기 때문입니다. 처음에'NULL '인지 확인해야합니다 (NULL이기 때문에 사용할 수 없습니다). 나는 대답을 연장했다. – Albert

+0

@PatrickBuhagiar : 어떤 컴파일러를 사용하고 있습니까? – alk

0

내가 당신의 구조가 어떻게 생겼는지 모르겠지만, 나는이 같은 추측하고있어 : 당신의 print 기능에

, 당신은 처음에이 검사를 추가해야합니다

struct { 
    int something; 
    int* value; 
    list* next; 
} 

h이 NULL 포인터인데도 h->valueh->next은 없습니다. 그들은 NULL+1NULL+2에있는 포인터이며 메모리의 임의의 위치를 ​​가리킬 수 있습니다.

+0

내 구조체는 int 값과 다음 포인터로 구성됩니다. 어떻게해야합니까? 내 말은, h-> NULL 값을 NULL로 설정할 수 없다는 것입니다. – User49230

1

문제는 아마도 게시하지 않은 코드 일 것입니다.

나는 당신이 당신의 목록에 '머리'포인터를 유지한다고 가정하고, 당신의 코드는 다음과 같이 보입니다.

Node * myList; 

.. do stuff.. 

destroy(myList); 
print(myList); 

문제는 파괴 된 후에 myList = NULL을 설정하지 않는 것이 문제입니다. 이 로컬 매개 변수를 수정 있기 때문에

destroy(myList); 
myList = NULL; 
print(myList); 

destroy()h=NULL 아무것도하지 않습니다.

+0

메인 메소드에서 null로 myList를 설정할 수 있는지 확실하지 않습니다 ... – User49230

+0

* 포인터를 전달해야하는 경우 * to myList - (print()를 수정하는 것을 포함하여) @Albert의 해결책을 참조하십시오. 재귀는리스트를 트래버스하는 추천 방법이 아닙니다! – Roddy

0

이 코드를 사용해보십시오 유는 리터 단독으로 작업하는 경우 체결 목록

void destroy(node *h){  
    node *n;  
    node *p; \\ variable to store previous term 
    n=h; 
    while(n->next!=NULL){ 
    p = n; 
} 
    p->next=NULL; 
    free(n); 

}

+0

이 코드는 del ete 한 번에 한 명씩 (마지막 학기). – Ashish

2

Albert 인해 몇 가지 규칙에 수 없습니다 solution provided하여, 당신은 에있는 저자 문제의 소스의는 것처럼 유일한 가능성이 목록의 기억 경우 노드가 할당을 취소하고 따라서 메모리에 대한 잘못된 참조가 포함되어 있고 후자 으로 인해 작성한 코드가 이러한 포인터를 역 참조하지 않을 수 있습니다. 즉, 인쇄 기능으로 전달되지 않을 수 있습니다 (). 이렇게하면 un/deallocated 메모리에 액세스하여 정의되지 않은 동작을 유발합니다.

잠재적 인 안전하지 않은 코드를 작성하는 경우 작성자가주의 깊게 사용하고 프로젝트를 종료 한 후 동료 프로그래머에게 코드를 잘 유지하도록 문서 작성자가 책임 져야합니다.