2014-12-27 6 views
0

Я пытаюсь добавить новый узел на структуру с голец * поля (слово)зЬгсру ошибка сегментации/strncmp в STRUCT fileds

Определение listT:

enum boolean {false, true}; 
struct list { 
    enum boolean sorted; 
    union{ 
     int words; 
     char *word; 
    }; 
    struct list* next; 
    struct list* previous; 
}; 
typedef struct list listT; 

Функция add_word_node вызывается главным образом как: add_word_node(read_word, list_head) где read_word предоставляется пользователем с помощью scanf. Слово проходит как строка, но после strncpy нет завершающего байта.

>Debugger: 
    add_word_node (word=0xbffff0fa "ally", head=0x804c038) at prog.c  
>Debugger: 
    (gdb) p newnode->word 


    $2 = 0x804c068 "allyP\224\373\267\377\377\377\377" 




listT *add_word_node(char word[], listT *head) { 
    listT *newnode; 
    listT *curr = NULL;//sorted 
    //listT *prev;//sorted 

    newnode = malloc(sizeof(listT)); /* allocate new node and check */ 
    newnode->word = malloc(sizeof(char)* WORDLEN); 
    strncpy(newnode->word, word, strlen(word)); 
    //newnode->word = strndup(word, strlen(word)); 


    if (newnode == NULL) { 
     return (NULL); 
    } 

    if (head->sorted == false){ //eisagwgh sto telos ths listas 
     newnode->next = head; 
     head->previous->next = newnode; 
     newnode->previous = head->previous; 
     head->previous = newnode; 
    }else { 
     if(head->next == head){ 
      newnode->next = head; 
      newnode->previous = head; 
      head->next = newnode; 
      head->previous = newnode; 

     }else{ 
      for (curr = head->next; curr->next != NULL; curr = curr->next){//for(curr = head->next; ;){ 
       if(curr == NULL) break; 
       if(strncmp(curr->word,newnode->word,strlen(word)) > 0) break; 
       //else curr= curr->next; 
      } 
      if(strncmp(curr->word,newnode->word,strlen(word))== 0){ 
       return(curr); 
      } 
      newnode->next = curr; 
      newnode->previous = curr->previous; 
      newnode->previous->next = newnode; 
      newnode->next->previous = newnode; 
     } 
    } 

    return (newnode); 

} 

Я прочитал некоторые другие темы об этой проблеме, и я изменил функцию, чтобы использовать слово [] вместо полукокса *, но он по-прежнему не работает. Скажите, пожалуйста, если вам нужна дополнительная информация. Кроме того, когда я использую strndup, он иногда работает без ошибок.

+0

Вы уверены, что когда 'curr = head-> next', head-> next не NULL? Потому что, когда это так, curr-> word даст уверенность seg. Да, это проблема. – Igor

+0

Я добавил оператор if, чтобы разбить цикл for в случае curr == NULL, но все равно получить тот же самый отказ seg. – user3163175

+0

В вашем цикле 'for' я проверил бы действительность' curr', а не просто переназначил ее в 'else':' for (cur = head-> next; curr-> next; curr = curr-> следующий) 'было бы немного более безопасным –

ответ

0

Как вы говорите, есть char *word, то этот указатель должен быть выделен память

newnode->word = malloc(sizeof(char) * (WORDLEN+1)); /* Please access the structure elements accordingly */ 

Память должна быть выделена указателем перед писать что-то на него.

+0

Doens't this: 'newnode = (listT *) malloc (sizeof (listT) + WORDLEN);' allocate memory for char * word? – user3163175

+0

@ user3163175 Я не могу видеть, что такое WORDLEN в коде, но не нужно просто выделять память вашей структуре и выделенной памяти указатель с структурой – Gopi

+0

Спасибо за информацию. Я изменил его, но я не думаю, что это решает проблему, поскольку WORDLEN больше, чем фактическая длина слов. – user3163175

0

Чтобы расширить @ ответ гопите немного:

Вашего заявления

newnode = (listT *) malloc(sizeof(listT) + WORDLEN); 

выделяет память для указателя newnode. Это означает, что, например, если WORDLEN совпадает с sizeof(listT), тогда вы будете выделять память для двух элементов listT для newnode. Это похоже на, скажем, char *ptr = malloc(2);, который будет выделять память для двух элементов char для ptr.

TL; DR: Эта память WORDLEN НЕ будет назначена newnode->word, она выделена newnode, и все. Чтобы устранить проблему, вы должны выделить память newnode->word отдельно. newnode не нуждается в этой памяти, но newnode->word делает.

strndup() работает, потому что он выделяет вам память.

Если вы все еще пытаетесь понять это, у вас могут возникнуть некоторые недоразумения в указателях.

newnode->word - указатель. Он имеет фиксированный размер на определенном компьютере (например, 8 байтов). Для простоты предположим, listT определяется следующим образом:

typedef struct { 
    char *word; 
} listT; 

Затем, когда вы выделяете память, вам нужно только выделить 8 байт newnode так, что он может содержать один указатель, а затем вам нужно выделить память для этого указателя, который будет использоваться для хранения некоторых символов.


Несмотря на то, что не связано с вашей проблемой, я также хотел бы указать, что вы не должны указывать возвращаемое значение malloc().См. Do I cast the result of malloc?