在每个节点上使用了 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;
}
我不能肯定地说没有其他错误 - 那只是有明显 “代码味道”的部分。
所以首先我有 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;
}
我不能肯定地说没有其他错误 - 那只是有明显 “代码味道”的部分。