2013-04-05 2 views
0

저는 C (및이 사이트)를 처음 접했고 세그멘테이션 오류와 관련하여 많은 문제가 있습니다. 연결된 숫자 목록을 만들고 오름차순으로 값을 삽입하는 프로그램을 작성했습니다.C 프로그래밍 세분화 오류 연결 목록 프로그램

 void insert(struct element **head, struct element *new){ 
      if((*head)->next == NULL && (*new).i > (*(*head)->next).i){ 
       (*head)->next = new; 
       return;  
      } 
      if((*head)->next == NULL && (*new).i < (*(*head)->next).i){ 
       new->next = (*head)->next; 
       *head = new;  
       return; 
      } 
      struct element *prev = *head; 
      struct element *current = (*head)->next; 
      while(current->next != NULL){ 
       if((*new).i < (*current).i){ 
        prev = current; 
        current = current->next; 
       } else if((*new).i > (*current).i){ 
        new->next = current; 
        prev->next = new; 
       } 
      } 
     } 
     int main (void){ 
      struct element **head; 
      int value; 
      printf("%s", "TEST"); 
      printf("%s" , "Please type in an integer value. "); 
      scanf("%d" , &value); 
      printf("%s", "TEST"); 
      do{ 
       printf("%s", "TEST"); 
       struct element *new; 
       if((new = malloc(sizeof(struct element))) == NULL){ 
       return(NULL); 
       } 
       printf("%s", "TEST"); 
       (*new).i = value; 
       printf("%s", "TEST"); 
       if(head == NULL){ 
        *head = new; 
        printList(*head); 
       } else if(value <= 0){ 
        printListBackwards(*head); 
       } 
       else { 

        insert(head, new); 
        printList(*head); 
       } 
       } while(value > 0); 

논리가 삽입되는 것과 맞는지 여부에 대한 도움이 필요하지 않습니다. 내가 프롬프트 후에 정수를 입력하면 즉시 세그먼트 오류가 발생하기 때문에 실제로 테스트 할 기회조차 없었습니다. 내가 펑키 보이지만, 스펙은 당신이 구조체 (링크 된리스트의 머리 부분)에 대한 포인터에 대한 포인터를 사용하도록 요구한다.

+1

코드를 공유 할 때 다른 사용자가 코드를 빠르게 컴파일하고 오류를 재현 할 수 있는지 확인하십시오. 당신의 코드는 구조 정의, 함수 그리고 심지어'main' 함수에서 닫는 중괄호가 빠져 있습니다. 또한 도움을 청하기 전에 컴파일 할 때 코드에 경고/오류가 표시되지 않는지 확인하십시오. '-Wall -Wextra' 플래그로 컴파일 해보십시오. segfaults를 알아 내면 나는 valgrind가 매우 유용한 도구라고 생각합니다. 디버깅 심볼을 생성하기 위해'-g' 플래그로 컴파일하는 것을 기억하십시오 –

답변

0

if((*head)->next == NULL && (*new).i > (*(*head)->next).i){ 
    (*head)->next = new; 
    return;  
} 

분할 결함 당신이 허용되지 않는 메모리에 액세스하려고하는 것을 의미한다 게시물의 두 번째 줄에 발생되는 독방 감금 오류가 있습니다. 예를 들어 NULL 포인터를 역 참조 할 수 없습니다.

if 성명은 이와 같이 평가됩니다. (*head)->next이 null인지 확인하십시오.

NULL이 아닌 경우 나머지는 건너 뜁니다.

NULL 인 경우 (*head)->next을 각각 NULL으로 바꿀 수 있습니다. 즉, 다음 부분은 && (*new).i > (*(*head)->next.i) 다음과 같이 다시 쓸 수 있습니다. && (*new).i > ((*NULL).i) ...

즉, NULL 포인터 값을 역 참조하려고합니다.

@Parker Kemp의 게시물을 참조하십시오. NULL을 올바르게 검사하지만 의미를 잘못 해석하는 경우가 많이 있습니다.

난 당신의 코드를 다시 작성할 수 있습니다하지만 난 당신이 내가 강력하게 데이터 구조의 다이어그램을 그리기 및 포인터에 대한 화살표를 그리기 추천 this one 또는 this one

같은 튜토리얼을 겪고에서 더 많은 혜택을 누릴 것이라고 생각합니다.

+0

감사합니다. 그 프로그램을 실행할 때 함수 삽입을 호출하기 전에 두 번째 "TEST"라인을 출력하지 못하는 이유를 설명해 주시겠습니까? 그리고 C에서 NULL을 확인하는 안전한 방법은 무엇입니까? – user2247284

+0

NULL에 대해 올바르게 테스트하고 있지만 올바른 비교를 사용하고 있지 않습니다. 'if (pointer == NULL) ... '는 포인터에 금지 된 메모리를 가리키는 NULL 값이 들어 있는지 알려줍니다. – nonsensickle

2

머리가 element**이고 머리가 element*이 아니겠습니까? 그 정도의 분리로 인해 문제가 발생합니다. 그 중 최소한의 것은 읽기 어려운 코드입니다.

if(head == NULL){ 
    *head = new; 
    printList(*head); 
} 

당신은 그 머리를 확인하고 NULL 포인터하고, 즉시 *으로 역 참조 그것을 시도 :

여기에 나를 밖으로 점프 중요한 것은입니다. 실제로 이중 포인터가되는 머리를 주장한다면, 역 참조하기 전에 동적으로 할당해야합니다. 이와 같이 :

if(head == NULL){ 
    head = malloc(sizeof(element*)); 
    *head = new; 
    printList(*head); 
} 

사실은 구문 상 완벽하지 않을 수 있습니다. C++에 대해서 말하자면, new은 C++의 키워드이기 때문에 일반적으로 C에서 변수 "new"의 이름을 지정하는 것은 나쁜 습관으로 간주됩니다.

+0

감사합니다. 헤드를 단일 포인터로 변경하고 더 잘 작동하는지 확인하겠습니다. 나는 아직도 프로그램을 실행할 때, 그것이 실패하기 전에 메인에서 두 번째 "테스트"라인을 출력하지 않는다는 것을 여전히 확신 할 수 없다. – user2247284

+0

@ user2247284 당신의 printf 문자열은 줄 바꿈으로 끝나지 않아서 플러시되지 않습니다. 또한, 단지 printf ("TEST \ n");' –

+0

을 수행하는 것이 일반적입니다. Jim이 말한 것을 확장하면, printf는 실제로 그렇게하지 않는 한 실제로 인쇄하지 않습니다. 프로그램에서 버퍼에 "TEST"를 넣었으나 아직 개행하지 않았으므로 기다리기로 결정했습니다. 그런 다음 버퍼를 플러시하기 전에 프로그램이 충돌합니다. –

0
struct element **head; 

원하지 않습니다.대신, 당신은 삽입을 호출 할 때

struct element *head = NULL; 

그런 다음,
insert(&head, new); 

당신은 다른 많은 버그와 가난한 용도가

를 사용하지만 특정 문제의 시작입니다.