【问题标题】:Adress is not stack'd, malloc'd or (recently) free'd地址未堆叠、malloc 或(最近)释放
【发布时间】:2016-02-07 19:21:29
【问题描述】:

我正在尝试将一些成员添加到基本链接列表中(而且我总是添加到列表的末尾)。

列表代码:

void createList(char * name, Test * node) {
    static int flag = 0;

    if(flag == 0 ){
        node->name = NULL;
        node->next = NULL;
        flag = 1;
    }

    Test * newNode;
    newNode = malloc(sizeof(Test));

    newNode->name = name;

    while(node->next != NULL) {
        node = node->next;
    }

    node->next = newNode;

    free(newNode);

}

我在这里使用静态变量来跟踪它是否是第一个函数调用(即列表为空)。

该函数本身可以正常工作,但是当我调用它来测试它(向列表中添加一些值)时:

int main(void) {
    Test * node;

    node = malloc(sizeof(Test));

    createList("TestName",node);

    printf("First Node in The List is %s\n",node->name); //segfaults

    return 0;
}

这似乎是段错误并给了我标题中的错误。 我的结构如下所示:

typedef struct Test Test;
typedef struct Test {
    char * name;
    Test * next;
} Test;

我没有标头节点(我无法更改),所以我使用的是静态变量。我认为这不是内存问题,但可能是我将下一个指针设置为新节点,但从未设置过原始的第一个节点?即它总是 NULL 导致段错误。任何帮助将不胜感激。

【问题讨论】:

  • (请不要冒犯)您的createList 功能是荒谬的。你能解释一下它的作用吗?以评论为例。
  • 那么静态标志在第一次调用时将结构值设置为 NULL(将值初始化为 NULL)。然后我创建一个新节点,对其进行 malloc,并将其名称设置为调用者提供的名称。我通过列表直到 node->next 不是 NULL (即在这种情况下它立即存在)。然后我将节点的下一个指针设置为新节点。我对链表不太熟悉,所以请尽可能更正我的代码。
  • 不!找一本解释链表的好书。

标签: c pointers segmentation-fault malloc


【解决方案1】:

当您执行node->next = newNode 时,您只需复制指针,这意味着您现在有两个指向同一内存的指针。然后,当您释放该内存时,您有两个指向未分配内存的指针。

试图取消引用这些指针中的任何一个都会导致未定义的行为

解决办法当然是不在新分配的内存上调用free


啊,上面其实不是你崩溃的原因,问题是你解引用了一个空指针。在你做的createList函数中

node->name = NULL;

然后在main 函数中尝试使用这个空指针。

main函数中,node是一个虚拟节点,其next指针将指向实际的第一个节点。

现在我还看到另一个问题:您没有初始化newNode->next,因此如果您尝试取消引用node->next->next,您将再次出现未定义的行为

【讨论】:

  • 删除对 free 的调用会保留 segfault 问题。删除 printf 行可以解决问题,因此访问 node->name 成员时出现问题。
  • @TEDED 啊,是的,我现在明白了,你正在做一个空指针访问。
【解决方案2】:

问题是在createList 中,您在将newNode 添加到列表后立即释放它,因此数据变得无效。只有在清理列表时才free

此外,列表中的第一个节点的name 总是等于NULL。因此,在 main 中的 printf 中,您尝试取消引用 NULL 指针,这会导致段错误。

最好不要在第一次调用时创建新节点,因为您已经有一个空节点:

void createList(char * name, Test * node) {
    static int flag = 0;

    if(flag == 0 ){
        node->name = strdup(name);
        node->next = NULL;
        flag = 1;
    } else {
        Test * newNode;
        newNode = malloc(sizeof(Test));
        newNode->name = strdup(name);

        while(node->next != NULL) {
            node = node->next;
        }

        node->next = newNode;
    }
}

【讨论】:

  • 这使它工作,谢谢!我想我离让它工作不远了。虽然(如果我错了,请纠正我)strdup 也会分配值,所以我以后必须释放它?
  • 是的,strdup 为字符串分配空间,所以你以后必须free 它。但是,您希望这样做,因为它使列表中的字符串独立于其来源。
【解决方案3】:

你有一个严重的问题:

node->next = newNode;

free(newNode);

你设置一个指向新节点的指针,然后你删除它。现在指针不会指向任何地方。

在您不再需要内存之前,您无法释放内存。

【讨论】:

  • 嗯,即使删除免费仍然似乎是段错误。
  • 是的,node->name 为 NULL,因为指向名称的指针存储在 newNode 中,而不是 node 中。
猜你喜欢
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 2020-04-07
  • 1970-01-01
  • 2019-08-21
  • 2018-10-12
  • 1970-01-01
相关资源
最近更新 更多