Неверный указатель кучи

Я практикуюсь в реализации кода связанного списка. поэтому я пишу код:

файл LinkedList.c

#include <stdio.h>
#include "function.h"
int main(void) {
    //initialize
    struct Node myNode = { 10,NULL };
    List head = &myNode;
    insert(20, head, head);
   
    makeEmpty(head);
   
    return 0;
}

файл function.h

//this is the statement of the Linkedlist
#ifndef _FUNCTION_H
#define _FUNCTION_H
struct Node;

//pointer to the strcut Node
typedef struct Node* PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;

struct Node
{
    //a struct pointer that point to next struct
    int element;
    //body
    Position Next;
    /* data */
};


//清空整张链表
List makeEmpty(List L);
//判断链表是否为空
int isEmpty(List L);
int isLast(Position p, List L);
Position Find(void* x, List L);
void insert(int x, List L, Position P);

#endif /*_function_h*/



файл List.c

#include "function.h"
#include <stdio.h>
#include <stdlib.h>
List makeEmpty(List L) {
    Position cur = L;
    Position next;
    while (cur!= NULL) {
        next = cur->Next;
        free(cur); 
        cur = next;
    }
    cur = NULL;
    next = NULL;
    //这里c是copy by value 所以改变那个指针,如果不赋值的话
    //就是用void的话,不会将原来的指针改变。
    L = NULL;
    return L;
}

//right
int  isEmpty(List L) {
    return L->Next == NULL;
}

int isLast(Position P, List L) {

    //判断P在不在List里
    List cur = L;
    while (cur->Next != P) {
        cur = cur->Next;
    }
    if (cur == NULL) {
        fprintf(stderr, "there is no P in the  list L\n");
        return  -1;
    }

    if (P->Next == NULL) {
        return 1;
    }
    else {
        return 0;
    }
    return -1;
}

void insert(int x, List L, Position P) {
    Position tmpCell;
    tmpCell = (Position)malloc(sizeof(struct Node));
    if (tmpCell == NULL) {
        fprintf(stderr,"out of the space!\n");
    }
    tmpCell->element = x;
    tmpCell->Next = P->Next;
    P->Next = tmpCell;
}

но когда я запускаю код, я получаю сообщение об ошибке: неверный указатель кучи, так почему

и когда я пишу head->Next в качестве параметра в функции «makeEmpty», она может работать, но почему в моей программе «head» указывает на первую структуру, поэтому head->Next должен указывать на вторую структуру . Я действительно озадачен.

Вам действительно не следует прятать указатели за typedef. Это значительно усложняет чтение и поддержку кода и поэтому широко признается как плохая практика.

Lundin 05.06.2024 14:47

Я написал в формате книги «Структуры данных и анализ алгоритмов в c», спасибо за совет.

user22873067 05.06.2024 15:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
94
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

TL;DR: Попробуйте проследить за жизненным циклом вашей переменной head.

Длинная версия:

Глава вашего списка — это указатель на локальную переменную main:

    struct Node myNode = { 10,NULL };
    List head = &myNode;

Тем не менее, вы пытаетесь освободить его:

    makeEmpty(head);

При первом вводе функции makeEmpty()cur будет равна head, а free(cur) завершится ошибкой, поскольку head — это адрес переменной в стеке, а не адрес, полученный с помощью malloc().

большое спасибо!!!!!!!!!!! хорошего дня. и я хочу использовать «牛逼», чтобы выразить свою благодарность

user22873067 05.06.2024 15:46
Ответ принят как подходящий

Указатель головы struct Node myNode = {10, NULL} является переменной стека и не может быть передан free().

Одним из простых решений этой проблемы является создание функции для инициализации нового узла:

PtrToNode
create_node(int x)
{
    PtrToNode tmp_node;

    tmp_node = malloc(sizeof(struct Node));
    if (tmp_node == NULL) {
        fprintf(stderr,"out of the space!\n");
        return NULL;
    }
    tmp_node->element = x;
    tmp_node->Next = NULL;
    return tmp_node;
}

После того, как вы сможете инициализировать свой список с новым узлом:

int
main(void) {
    //initialize
    List my_list = NULL;
    
    my_list = create_node(10);
    insert(20, my_list , my_list);
    makeEmpty(my_list);
    return 0;
}

большое спасибо!!!!!!!!!!! хорошего дня. и я хочу использовать «牛逼», чтобы выразить свою благодарность

user22873067 05.06.2024 15:45

Как указывают другие ответы, вы не можете free() объекты, которые не были выделены malloc() или аналогичными функциями.

Одним из ограничений функции insert является то, что она не поддерживает вставку в начало списка. Это можно поддержать, изменив его так, чтобы он вставлялся в начало списка, когда P равен NULL. Также необходимо будет вернуть нового руководителя списка. Вот возможная реализация:

В функции.h:

List insert(int x, List L, Position P);

В списке.c:

List insert(int x, List L, Position P) {
    Position tmpCell;
    tmpCell = (Position)malloc(sizeof(struct Node));
    if (tmpCell == NULL) {
        fprintf(stderr,"out of the space!\n");
    }
    tmpCell->element = x;
    if (P == NULL) {
        tmpCell->Next = L;
        L = tmpCell;
    }
    else {
        tmpCell->Next = P->Next;
        P->Next = tmpCell;
    }
    return L;
}

Переработанную функцию можно использовать для создания всех элементов списка…

В LinkedList.c:

#include <stdio.h>
#include "function.h"
int main(void) {
    List head = insert(10, NULL, NULL); // insert to empty list
    insert(20, head, head); // insert after first element of list
    head = insert(0, head, NULL); // insert at beginning of list
   
    makeEmpty(head);
   
    return 0;
}

Другие вопросы по теме