Почему я получаю ошибку сегментации при печати содержимого моего связанного списка?

#c #linked-list #segmentation-fault #stack #malloc

#c #связанный список #ошибка сегментации #стек #malloc

Вопрос:

Я пытаюсь реализовать структуру в стиле стека, используя связанный список в C. В конечном итоге он будет считывать строки различной длины из входного файла, следовательно, потребность в динамической памяти. Я получаю ошибку сегментации в printf в printList и не могу понять, почему. Я также получал ошибки сегментации в push ранее, но, похоже, я их исправил. В случае, если это не очевидно, мое намерение состоит в том, чтобы добавлять элементы только в «верхнюю» часть списка.

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>


void* emalloc(size_t n);

typedef struct node {
    struct node* next;
    char* word;
} node;

node* head = NULL;

void* emalloc(size_t n) {
    void* p;
    p = malloc(n);
    if(p == NULL) {
        fprintf(stderr, "Failed to allocate memory.");
        exit(1);
    }
    return p;
}

void push(char* w) {
    if(head == NULL) {
        head = (node*) emalloc(sizeof(node));
        head->word = (char*) emalloc(strlen(w) * sizeof(char)   1);
        strncpy(head->word, w, strlen(w)   1);
        printf("Pushed a word to head.");
        return;
    }

    node* newnode = (node*) emalloc(sizeof(node));
    newnode->word = (char*) emalloc(strlen(w) * sizeof(char)   1);
    strncpy(newnode->word, w, strlen(w)   1);
    newnode->next = head;
    head = newnode;
}

void printList() {
    node* cur = head;
    if(cur == NULL || cur->word == NULL) printf("Whoops!");
    while(cur != NULL) {
        printf(cur->word);
        cur = cur->next;
    }
}


/*
 * The encode() function may remain unchanged for A#4.
 */

void main() {
    char word[20] = "Hello world";
    //push("Hello",head);
    //push("World",head);
    //push("!",head);
    push(word);
    printList();
}
  

Ответ №1:

Зачем копировать в 1 последний конец строки в push()? Кроме того, если строка слишком длинная, strncpy не обнулит ее для вас.

Однако настоящая ошибка заключается в создании «Head», первом операторе if, когда записей не существует. Он не обнуляет свой следующий указатель, поэтому обход списка будет прерван при последней записи, поскольку он считывает указатель мусора в конце списка.

Ответ №2:

у меня это сработало, поскольку Майкл Дорган спросил, почему вы пропустили 1 байт после конца строки.

Я рекомендую использовать что-то вроде :

 int len =strlen(w)
  

перед

 node* newnode = (node*) emalloc(sizeof(node));
newnode->word = (char*) emalloc(len * sizeof(char));
strncpy(newnode->word, w, len)[len]=0;
newnode->next = head;
  

эта временная переменная устраняет необходимость использования strlen в этих местах.