简体   繁体   中英

strcpy / strncmp segmentation fault in struct fileds

I'm trying to add a new node to a struct with a char* field (word)

Definition of 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 function is being called by main as: add_word_node(read_word, list_head) where read_word is given by the user with scanf. Word is being pass as a string but after strncpy there is no terminating byte.

>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);

}

I have read some other topics about this problem and I changed the function to use word[] instead of char* but it still doesn't work. Please tell me if you need more info. Also, when I use strndup, it sometimes work without any error.

As you say you have a char *word then this pointer should be allocated memory

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

Memory should be allocated to the pointer before writing something to it.

To expand @Gopi's answer a bit:

Your statement

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

allocates memory to the pointer newnode . This means that, for example if WORDLEN is the same as sizeof(listT) , then you will be allocating memory for two listT elements for newnode . This is similar to, say, char *ptr = malloc(2); which will allocate memory for two char elements for ptr .

TL;DR: This WORDLEN memory will NOT be allocated to newnode->word , it is allocated to newnode , and that's that. To fix your problem, you must allocate memory to newnode->word separately. newnode does not need that memory, but newnode->word does.

strndup() works because it allocates the memory for you.

If you still struggle to understand this, you may have some misconceptions on pointers.

newnode->word is a pointer. It has a fixed size on a certain machine (eg 8 bytes). For simplicity assume listT is defined as follows:

typedef struct {
    char *word;
} listT;

Then when you allocate memory, you only need to allocate 8 bytes to newnode so that it can hold one pointer, and then you need to allocate memory to that pointer, which will be used to store some characters.


Although not related to your problem, I would also like to point out that you shouldn't cast the return value of malloc() . See Do I cast the result of malloc?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM