Ошибка сегментации попытки загрузки функции

Я продолжаю получать 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 во время инициализации. У меня есть три типа узлов: корневой, обходной (для перемещения) и следующий_узел. (i.) Можно ли обнулить узлы перед их выделением? (ii.) Кроме того, как мне освободить «next_node», если этот узел инициализирован и распределен внутри оператора if? node *next_node = malloc(sizeof(node)); (iii.) Если я хочу установить узлы как глобальные переменные, какие из них должны быть глобальными? (iv.) И, наконец, где я могу установить глобальные переменные: внутри main файла Sppeler.c, вне его main или где-то еще? Вопросов много, поэтому вам не обязательно отвечать на все из них, но было бы неплохо, если бы вы ответили на те, на которые уже есть ответы! Пожалуйста, укажите любые другие особенности в моем коде. Должно быть много. Я приму большинство ответов.


person Jason    schedule 05.09.2017    source источник
comment
Вам нужно отладить свой код, чтобы выяснить, в какой строке ваш код дает ошибку. Вам также необходимо выполнить обработку ошибок и проверку в вашем коде. например эти строки: int alpha = (tolower(*c) - 97); if(trav -> children[alpha] == NULL) это не то, что вы можете сделать, вы должны знать, действителен ли ваш ввод, поэтому вы должны проверить, является ли alpha >= 0 и < 27, прежде чем вы сможете продолжить и использовать его в качестве индекса в trav -> children[alpha]   -  person nos    schedule 05.09.2017
comment
char *c = NULL; Вы никогда не выделяли память для c, поэтому fscanf дает сбой при записи в нее.   -  person Matt    schedule 05.09.2017
comment
fscanf нужен указатель на место для хранения входящих данных. Вы установили c в NULL и передали это fscanf, поэтому, когда вы читаете строку, она пытается писать через нулевой указатель. Создайте строковый буфер, скажем, из 256 символов и передайте его в качестве аргумента fscanf.   -  person aghast    schedule 05.09.2017
comment
Кроме того, когда вы выделяете новый узел, вы не обнуляете память. Попробуйте вместо этого позвонить calloc. Еще лучше написать отдельную функцию для выделения, инициализации и возврата указателя узла.   -  person aghast    schedule 05.09.2017
comment
Что будет делать функция возврата?   -  person Jason    schedule 06.09.2017


Ответы (1)


Причиной ошибки сегментации является указатель "c", которому вы не выделили память.

Кроме того, в вашей программе -

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

Как только вы выделите память для указателя c, c будет хранить слово, прочитанное из файлового словаря. Ниже в вашем коде вы проверяете символ «\ 0» -

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

Но вы не перемещаете указатель c, чтобы он указывал на следующий символ в прочитанной строке, из-за чего этот код в конечном итоге будет выполнять бесконечный цикл while. Можете ли вы попробовать что-то вроде этого-

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