【发布时间】: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返回的指针完全相同。malloc和free不需要在同一个函数中或同时调用。但在程序的某个时刻,每个malloc都应该有一个free。 -
free不会“从列表中删除节点”。你的程序必须从列表中删除节点,一旦你完成了,你调用free告诉系统你不再使用那个内存。
标签: c malloc hashtable free cs50