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

Я пытаюсь реализовать структуру стека-esque, используя связанный список в 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();
}

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

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

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

0 голосов
/ 06 апреля 2019

это сработало для меня, поскольку Майкл Дорган спросил, почему вы прошли 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 в этих местах.

...