2017-09-05 9 views
0

로드 기능에 segfault가 계속 발생합니다.로드 기능 트라이 세그먼트 화 오류

bool load(const char *dictionary) 
{ 
    //create a trie data type 
    typedef struct node 
    { 
     bool is_word; 
     struct node *children[27]; //this is a pointer too! 
    }node; 

    //create a pointer to the root of the trie and never move this (use traversal *) 
    node *root = malloc(sizeof(node)); 
    for(int i=0; i<27; i++) 
    { 
     //NULL point all indexes of root -> children 
     root -> children[i] = NULL; 
    } 


    FILE *dptr = fopen(dictionary, "r"); 
    if(dptr == NULL) 
    { 
     printf("Could not open dictionary\n"); 
     return false; 
    } 



    char *c = NULL; 


    //scan the file char by char until end and store it in c 
    while(fscanf(dptr,"%s",c) != EOF) 
    { 
     //in the beginning of every word, make a traversal pointer copy of root so we can always refer back to root 
     node *trav = root; 

     //repeat for every word 
     while ((*c) != '\0') 
     { 
     //convert char into array index 
     int alpha = (tolower(*c) - 97); 

     //if array element is pointing to NULL, i.e. it hasn't been open yet, 
     if(trav -> children[alpha] == NULL) 
      { 
      //then create a new node and point it with the previous pointer. 
      node *next_node = malloc(sizeof(node)); 
      trav -> children[alpha] = next_node; 

      //quit if malloc returns null 
      if(next_node == NULL) 
       { 
        printf("Could not open dictionary"); 
        return false; 
       } 

      } 

     else if (trav -> children[alpha] != NULL) 
      { 
      //if an already existing path, just go to it 
      trav = trav -> children[alpha]; 
      } 
     } 
     //a word is loaded. 
     trav -> is_word = true; 
    } 
    //success 
    free(root); 
    return true; 
} 

초기화하는 동안 새 포인터가 NULL을 가리키는 지 확인했습니다. 루트, 순회 (이동) 및 next_node의 세 가지 유형의 노드가 있습니다. (i.) 노드를 malloc하기 전에 노드를 null로 지정할 수 있습니까? (ii.) 또한 노드가 초기화되고 if 문 내부에서 malloc되면 'next_node'를 해제 할 수 있습니까? node *next_node = malloc(sizeof(node)); (iii.) 글로벌 변수로 노드를 설정하려면 어느 것이 글로벌해야합니까? (iv.) 마지막으로, 전역 변수를 어디에 설정합니까? speller.c의 메인 내부, 메인 외부 또는 다른 곳에서? 그것은 많은 질문들입니다. 그래서 그들 모두에 대답 할 필요는 없지만, 대답 한 대답에 대답 할 수 있다면 좋을 것입니다! 제 코드의 다른 특징을 지적하십시오. 많아야합니다. 나는 대부분의 대답을 받아 들일 것이다.

+0

뭔가를 시도 할 수있다, 그래서 당신은있는 코드의 세그먼테이션 폴트 (segfault)를 줄 알아. 또한 코드에서 오류 처리 및 유효성 검사를 수행해야합니다. 예 : 다음 줄은 : int alpha = (tolower (* c) - 97); if (trav -> children alpha == NULL)'이 할 수있는 일이 아니라면 입력이 유효한지 알아야하므로 'alpha'가'> = 0'이고'<27 ''trav -> children [alpha]' – nos

+1

'char * c = NULL; '에서 인덱스로 사용할 수 있습니다. fscanf가 쓰기 작업을하는 동안 fscanf가 오류를 일으키지 않습니다. – Matt

+0

'fscanf'는 들어오는 데이터를 저장할 곳을 가리키는 포인터를 원합니다. 'c'를'NULL'로 설정하고'fscanf'에 넘겨 주면 라인을 읽을 때 널 포인터를 쓰려고합니다. 예를 들어, 256 문자의 라인 버퍼를 만들고이를 fscanf에 인수로 전달하십시오. –

답변

0

세그먼트 화 오류의 원인은 메모리를 할당하지 않은 포인터 "c"입니다. 프로그램에서 또한

, - 당신이 포인터 C에 메모리를 할당하면

//scan the file char by char until end and store it in c 
while(fscanf(dptr,"%s",c) != EOF) 

, C는 파일 사전에서 읽은 단어를 개최한다. 코드에서 아래 , 당신은 '\ 0'를 확인하는이

while ((*c) != '\0') 
    { 

을 문자 -하지만 당신은 때문에이 코드가 무한 실행 끝날 것이다 읽을 문자열에서 다음 문자를 가리 키도록 C 포인터를 이동하지 않습니다 while 루프. 당신은 당신은 당신의 코드를 디버깅 할 필요가 this-

char *tmp; 
tmp = c; 
while ((*tmp) != '\0') 
{ 
    ...... 
    ...... 
    //Below in the loop at appropriate place 
    tmp++; 
}