【问题标题】:Difference between free() function with or without malloc带或不带 malloc 的 free() 函数之间的区别
【发布时间】:2021-01-18 13:29:18
【问题描述】:

这是 cs50 pset5 拼写器的一部分。背景是我将字典加载到带有链表的哈希表中,并根据哈希表检查单词以确定该单词是否在字典中,然后我卸载哈希表。

当我加载字典时,我使用 malloc() 和 free() 将一个节点插入到链表中。 free() 这里的结果是它释放了分配给指针的内存,但它不会删除指针对象(在这种情况下是插入到链表中的节点)。 这是我的代码:

bool load(const char *dictionary)
{
    FILE *inputfile = fopen(dictionary, "r");
    if (inputfile == NULL)
    {
        return false;
    }

    char tempWord[LENGTH+1];

    while (fscanf(inputfile, "%s", tempWord) != EOF)
    {
        //create a tempNode and make sure
        node *tempNode = malloc(sizeof(node));
        if (tempNode == NULL)
        {
            return false;
        }

        strcpy(tempNode->word, tempWord);
        tempNode->next = NULL;

        //get the index of this word
        int index = hash(tempWord);

        //move tempNode to the next node in the linked list
        if (table[index]->next != NULL)
        {
            tempNode->next = table[index];
        }

        table[index]->next = tempNode;

        free(tempNode);

        word_count ++;
    }
    fclose(inputfile);

    return true;
}

当我卸载字典时,我再次使用了 free(),但这次根本没有调用 malloc()。这样链表上的元素就可以一个个的被释放了。 free() 的结果是它从链表中“移除”了节点 这是我的代码:

bool unload(void)
{
    for (int i = 0; i < N; i ++)
    {
        //freeing linked list, we need two tempNode in order to do this
        node *tempPtr = table[i];
        while (tempPtr != NULL)
        {
            node *deletePtr = tempPtr;
            tempPtr = tempPtr->next; //move the tempPtr to the next element, so we are note losing the linked list
            free(deletePtr); //once we moved the tempPtr to the next element, now we can delete where deletePtr is pointing at
        }
    }
    return true;
}

虽然我的代码已经编译并且可以毫无问题地运行,但我很困惑为什么 free() 在这里做不同的事情。

总结一下我的问题:

(1)我说得对吗:在“加载”中,free(tempNode) 不会“擦除” tempNode 指向的内容(它是链表中的一个节点),而只是释放分配给的内存临时节点;然而,在 'unload' 中,free(deletePtr) 'erase' 都删除了 deletePtr 和 deletePtr 指向的内容(它是链表中的一个节点)?

(2) 如果我在 (1) 中的观察是正确的,为什么 free() 在这里做不同的事情?这是因为 load 调用 malloc() 和 unload 没有引起的吗?

(3) 我知道如果我调用了 malloc(),我必须调用 free(),但是当 malloc() 没有被调用时,free() 会做什么?

================================== 编辑: 经过更多研究,我意识到在加载部分,没有必要释放 malloc() 分配的内存。原因是,在卸载部分,通过free()每个节点,我最终能够释放之前分配的内存。

【问题讨论】:

  • 这很简单。每个malloc 必须恰好有一个free。不是二,不是零,不是其他任何东西——正好是一。并且传递给free 的指针必须与malloc 返回的指针完全相同。 mallocfree 不需要在同一个函数中或同时调用。但在程序的某个时刻,每个malloc 都应该有一个free
  • free 不会“从列表中删除节点”。你的程序必须从列表中删除节点,一旦你完成了,你调用free告诉系统你不再使用那个内存。

标签: c malloc hashtable free cs50


【解决方案1】:

(1)我这样说是否正确:在“加载”中,free(tempNode) 没有 '擦除' tempNode 指向的内容(它是链接中的节点 list),但只释放分配给 tempNode 的内存;

tempNode 指向的对象与tempNode 指向的对象占用的内存没有有意义的区别。如果那是一块动态分配的内存,那么在释放它之后你不能尝试访问它。任何这样做的尝试都会产生未定义的行为。

因此这个问题毫无意义。没有一致的方法来判断有问题的内存是否已被“擦除”,因为您不能尝试读取它。如果您确实尝试读取它,那么程序可能会表现得好像内存已以某种方式被覆盖,或者它可能不会。它也可能在其权力范围内做任何其他事情。使程序崩溃(最终)是一种流行的替代方法,但绝不是一种保证。

在“卸载”中, 但是,free(deletePtr) '擦除' deletePtr 和 deletePtr 是什么 指向(链表中的节点)?

见上文。

(2) 如果我在 (1) 中的观察是正确的 [...]

观察(1)不正确。

(3) 我知道如果我调用了 malloc(),我必须调用 free(),但是当 malloc() 没有被调用,free() 是做什么的?

如果向free() 函数传递了一个非空指针值并且不是从内存分配函数获得的,或者已经被释放的指针值,则free() 函数具有未定义的行为(见上文)。

【讨论】:

    猜你喜欢
    • 2012-08-29
    • 2011-11-27
    • 1970-01-01
    • 2012-09-29
    • 2011-05-05
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    相关资源
    最近更新 更多