Связанный список в c добавление в начало списка - PullRequest
2 голосов
/ 11 марта 2020

Я пытаюсь создать простую программу для добавления значения в связанный список. код компилируется без ошибок. Я получаю ошибку сегментации при попытке выполнить файл. Я пытался отлаживать с помощью операторов printf, но я не получаю вывод нигде. Может кто-то указать, что я делаю не так.

typedef struct в отдельном файле .h, включить файлы также в отдельный файл .h

typedef struct      s_list
    {
        struct s_list   *next;
        void            *data;
    }                   t_list;


void    list_push_front(t_list **begin_list, void *data)
{
    t_list *l;

    l = (t_list*)malloc(sizeof(t_list));
    if(l == NULL){
        printf("No allocation");
    }
    printf("%s\n", l->data);
    l->data = data;
    l->next = *begin_list;
    *begin_list = l;
    printf("%s\n", l->data);

}

int     main(void)
{
    t_list *k;
    k = (t_list*)malloc(sizeof(t_list));
    if(k == NULL){
        printf("No allocation");
    }
    printf("allocation");
    char s[] = "Woow!";
    k->data = "Hello";
    k->next->data = NULL;
//  k->next->next->data = NULL;
    list_push_front(&k, s);
    return(0);
}

Ответы [ 2 ]

1 голос
/ 11 марта 2020

При вызове printf

l = (t_list*)malloc(sizeof(t_list));
if(l == NULL){
    printf("No allocation");
}
printf("%s\n", l->data);

вы пытаетесь вывести неинициализированную память, на которую указывает указатель l->data. Таким образом, функция вызывает неопределенное поведение. Удалить этот вызов printf. Это не имеет смысла.

Также в основном это утверждение

k->next->data = NULL;

неверно и также вызывает неопределенное поведение. Кажется, вы имеете в виду

k->next = NULL;
0 голосов
/ 11 марта 2020

Как правило, всегда компилируйте с флагами -Wall -Werror и часто выполняйте код (каждую пару строк). Это должно помочь избежать многих проблем здесь. Используйте valgrind, asan или gdb для обнаружения и диагностики проблем с памятью, подобных тем, которые есть в этой программе.

  • k->next->data = NULL; недопустимо, поскольку k->next не инициализировано.
  • printf("%s\n", l->data);, та же проблема. Вы должны инициализировать значение перед использованием.
  • Функции не должны вызывать побочных эффектов, таких как печать. Это нормально для временной отладки, но помимо этого это делает для шумных программ и по существу непригодных для использования функций. Если вам нужны ошибки, распечатайте в stderr и выйдите или используйте возвращаемые значения, такие как enum или NULL, чтобы указать ошибки.
  • Всегда free выделенная память.
  • Нет необходимости для приведения результата malloc.
  • Используйте последовательные отступы и форматирование.

Возможное переписывание:

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

typedef struct ListNode {
    struct ListNode *next;
    void *data;
} ListNode;

ListNode *list_create(void *data) {
    ListNode *node = malloc(sizeof(*node));

    if (!node) {
        fprintf(stderr, "%s %d: malloc failed\n", __FILE__, __LINE__);
        exit(1);
    }

    node->data = data;
    node->next = NULL;
    return node;
}

void list_push_front(ListNode **head, void *data) {
    ListNode *node = list_create(data);
    node->next = *head;
    *head = node;
}

void list_free(ListNode *head) {
    while (head) {
        ListNode *dead = head;
        head = head->next;
        free(dead);
    }
}

int main(void) {
    ListNode *list = list_create("a");
    list_push_front(&list, "b");
    list_push_front(&list, "c");

    for (ListNode *curr = list; curr; curr = curr->next) {
        printf("%s\n", (char *)curr->data);
    }

    list_free(list);
    return 0;
}
...