在每个节点上使用了 free() 但它没有清空列表?

Used free() on each node but it's not emptying the list?

所以首先我有 2 个链表,一个在另一个链表中(就像一个矩阵),我做了一个函数来删除整个节点。它似乎正在释放但是当我打印值 t 时它输出奇怪的字符。

这是列表中使用的结构

typedef struct
{
    char codigo[LEN_CODIGO + 1];
    char partidaID[LEN_ID + 1];
    char chegadaID[LEN_ID + 1];
    Data datapartida;
    Tempo horapartida;
    Tempo duracao;
    Data datachegada;
    Tempo horachegada;
    int capacidade;
    int ocupacao;
} Voo;

typedef struct r
{
    char *codReserva;
    int nPassangeiros;
    struct r *next;
} *ListaReservas;

typedef struct node
{
    Voo voo;
    ListaReservas nodeReservas; /*this is the head to a list inside this list*/
    struct node *next;
} *Node;

在下面的函数中我假装删除一个节点和其中的nodeReservas的所有节点,就像删除矩阵的一整列。

Node eliminaNode(Node head, char codigo[])
{
    Node n, prev;
    ListaReservas r, temp;
    for (n = head, prev = NULL; n != NULL; prev = n, n = n->next)
    {
        if (strcmp(n->voo.codigo, codigo) == 0) /*If it's the correct node*/
        {
            if (n == head)
                head = n->next;
            else
                prev->next = n->next;
            /*deletes nodeReservas*/
            r = n->nodeReservas;
            temp = r;
            while(temp != NULL)
            {
                temp = temp->next;
                free(r->codReserva);
                free(r);
                r= temp;
            }
            /*deletes the whole node*/
            free(n);
        }
    }
    return head;
}

然后我使用此代码告诉我节点中仍然存在哪些预留

for (r=n->nodeReservas; r != NULL; r= r->next)
    printf("%s %d\n", r->codReserva, r->nPassangeiros);

例如,在将 3 个预留添加到假设节点 X 并使用 eliminaNode(headofList, X) 删除具有预留的节点之后。在重新创建具有相同名称 'X' 的节点并打印其保留后,我得到的不是空行,而是:

 -725147632
�+���U -725147632
@+���U -725147632

那么什么是 free() 释放?发生这种情况是因为 Lista reservas 是一个指针吗?

free() returns 分配到堆的块,它可能 re-used 用于后续分配请求。它不会(怎么可能?)修改指向该块的指针,如果您保留这样的指针并在 de-allocation 之后 re-use 它,将不会发生任何好事。

你应该做的是在释放块后立即将指针设置为 NULL(或有效指针,例如新的下一个节点的指针),这样你就不会保留对现在无效块的引用:

                free(r->codReserva);
                r->codReserva = NULL ;

                free(r);
                r= temp;
            }
            /*deletes the whole node*/
            free(n);
            n = NULL ;

这样做应该是C代码的习惯。你可以通过创建一个函数来简化事情说:

void dealloc( void** ref )
{
    free( *ref ) ;
    *ref = NULL ;
}

那么您可以调用 dealloc( &n ) 而不是调用 free( n )

此代码还有其他严重问题。例如,涉及 temp 的代码有点 over-complicated(任何带有变量 temp 的代码都应该引起警钟——你已经给它赋予了整个函数的作用域,并且使用它的时间超过了一个目的 - 这不是好的做法)。考虑:

            r = n->nodeReservas;
            while( r != NULL)
            {
                ListaReservas new_next= r->next;

                free(r->codReserva);
                r->codReserva = NULL ;

                free(r);
                r = new_next;
            }

那里 new_next 非常本地化(字面意思是“临时”)并且命名得当所以很清楚它是什么。下一个问题是,分配了值 r 后,您什么都不做!您打算更新的大概是 n->nodeReservas 而不是 r?也许:

            ListaReservas r = n->nodeReservas;
            while( r != NULL)
            {
                ListaReservas new_next= r->next;

                free(r->codReserva);
                r->codReserva = NULL ;

                free(r);
                n->nodeReservas = new_next;
            }

请注意在每种情况下临时变量的声明在首次使用时,以提供最窄的范围。请注意 r 也是临时的。然而,这里并不是真正必要的——它只是 n->nodeReservas 的 shorthand——我个人会根除它——如果只是为了完全避免上述错误。对单个分配有多个引用是错误的秘诀。相反:

            while( n->nodeReservas != NULL)
            {
                ListaReservas new_next = n->nodeReservas->next;

                free(n->nodeReservas->codReserva);
                n->nodeReservas->codReserva = NULL ;

                free(n->nodeReservas);
                n->nodeReservas = new_next;
            }

我不能肯定地说没有其他错误 - 那只是有明显 “代码味道”的部分