这是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)是我正确地说:在“ load”中,free(tempNode)不会“擦除” tempNode指向的内容(它是链接列表中的一个节点),而只是释放分配给tempNode;但是,在“卸载”中,free(deletePtr)是否“擦除” deletePtr和指向的是deletePtr(指向链表中的一个节点)?
(2)如果我对(1)的观察是正确的,为什么free()在这里做不同的事情?这是由于调用malloc()和unload的事实没有引起的吗?
(3)我知道如果我调用了malloc(),则必须调用free(),但是当不调用malloc()时,free()会做什么?
================================= 修改: 经过更多研究,我意识到在load部分,没有必要释放()由malloc()分配的内存。原因是,在卸载部分,通过每个节点的free(),我最终将能够释放之前分配的内存。
答案 0 :(得分:1)
(1)是我正确地说:在'load'中,free(tempNode)不 “擦除” tempNode指向的内容(这是链接的节点 列表),但仅释放分配给tempNode的内存;
tempNode
指向的对象与tempNode
指向的对象所占用的内存没有有意义的区别。如果那是一块动态分配的内存,则释放它后一定不要尝试访问它。任何尝试这样做都会产生不确定的行为。
因此,这个问题毫无意义。没有确定内存是否已“擦除”的一致方法,因为您不得尝试读取它。如果您确实尝试读取它,则程序可能会表现得好像是以某种方式覆盖了内存,或者可能没有。它也可能在力所能及的范围内做其他任何事情。 (最终)崩溃程序是一种流行的选择,但绝不能保证。
在“卸载”中, 但是,free(deletePtr)'擦除'deletePtr和删除的东西是什么 指向(链接列表中的一个节点)?
见上文。
(2)如果我在(1)中的观察是正确的[...]
观察(1)不正确。
(3)我知道如果我调用了malloc(),则必须调用free(),但是当 没有调用malloc(),free()会做什么?
如果free()
函数传递了一个非空且不是从内存分配函数获得的指针值或已经释放的指针值,则该函数具有未定义的行为(请参见上文)。