1

我想在 C 中释放一个链表。一切正常,但 Valgrind 告诉我

Conditional jump or move depends on uninitialised value(s)
    at 0x401400: mtf_destroy

这是代码:

list_elt *head;

void mtf_init() {
    list_elt *current;
    head = malloc(sizeof(list_elt));
    current = head;
    for (int i = 0; i < LIST_SIZE-1; i++) {
        current->value = (BYTE) i;
        current->next = malloc(sizeof(list_elt));
        current = current->next;
    }
    current->value = LIST_SIZE-1;
}

void mtf_destroy(list_elt *elt) {
    if (elt->next != NULL)
        mtf_destroy(elt->next);
    free(elt);
}

我该如何解决这个问题?谢谢!

4

1 回答 1

4

Valgrind 想告诉你elt->nextused as expression的实例if()没有被初始化,所以做出的决定if()是随机的。

您可能想更改:

head = malloc(sizeof(list_elt));
...
  current->next = malloc(sizeof(list_elt));

成为:

head = calloc(1, sizeof(list_elt));

..."
  current->next = calloc(1, sizeof(list_elt));

一种可移植的方法是使用以下命令显式初始化所有指针NULL

head = calloc(1. sizeof(list_elt));
head->next = NULL;
...
  current->next = calloc(1, sizeof(list_elt));
  current->next->next = NULL;

(其背景是,并非在所有系统上,NULL指针都必须由一系列NUL字符(字节)表示)。

无论如何,我不确定您是否分配了正确的东西,next因为您没有发布list_elt.


更新:

关于递归调用mtf_destroy()

尽管递归看起来很酷,并且确实是许多问题的优雅解决方案,但使用它们往往容易出错,例如在非常深入的情况下,因为它们会消耗系统资源(内存)。

因此,如果您的列表真的很长,那么销毁它可能会破坏您的代码。

我的建议:尝试不使用递归,至少如果您无法提前预测要执行的递归级别。

于 2012-11-24T10:46:04.393 回答