编辑1
根据{{3}}的建议,我现在不使用以下划线开头的名称,也删除了->
周围的空格。
的 ------------------------------------------------------------------------
在尝试使用递归函数释放struct时,我遇到了段错误。
这是我的结构:
//creating new trie data ctructure
typedef struct dict
{
bool is_word;
struct dict *children[ALPHABET+1];
}
node;
它用于存储在拼写检查器中使用的字典。在程序结束时,我需要释放所有已分配的内存。
这是我写的功能。它应该自称并且一块一块地自由发送。然而,在多次调用自己之后,它给了我段错误。
bool unload(void)
{
// Check if root
if (temp == root)
{
for (int i = 0; i < ALPHABET+1; i++)
{
if (!temp->children[i] && i != ALPHABET)
{
}
else if (!temp->children[i] && i == ALPHABET)
{
free(temp);
return true;
}
else if(temp->children[i])
{
temp = temp->children[i];
unload();
}
}
}
else
{
for (int i = 0; i < ALPHABET+1; i++)
{
if (!temp->children[i] && i != ALPHABET)
{
}
else if (!temp->children[i] && i == ALPHABET)
{
temp1 = temp;
temp->children[i] = temp;
free(temp1);
return true;
}
else if (temp->children[i])
{
temp = temp->children[i];
unload();
}
}
}
return false;
}
假设root,temp,temp1是全局的。所有这些都是struct _dict。并且当第一次调用函数temp == root。
时答案 0 :(得分:0)
您的代码正在证明为什么全局变量是一个坏主意,并且适得其反。您应该将要释放的节点传递给该函数;初始调用通过根节点。该函数不需要访问任何全局变量。
另请注意,点.
和箭头->
运算符绑定非常紧密,不应使用它们周围的任何空格。此外,以下划线开头的名称基本上保留供实现使用。 The full details are more nuanced比那更多,但不是很多。最简单的方法是避免在您发明的名称中使用下划线。仅将它们用于访问系统提供的设施。
这段代码做了必要的事情,假设分配node
的代码确保所有指针都为空。
#include <stdlib.h>
#include <stdbool.h>
enum { ALPHABET = 26 };
typedef struct dict
{
bool is_word;
struct dict *children[ALPHABET+1];
} node;
void unload(node *item);
void unload(node *item)
{
for (int i = 0; i < ALPHABET+1; i++)
{
if (item->children[i] != 0)
unload(item->children[i]);
}
free(item);
}
在使用它之前,可以修改代码以测试item
是否为NULL。因此,循环中的条件并不是绝对必要的,但如果在分配任何节点之前调用它,则整体函数会更具弹性。
如图所示,它使用这些相当严格的警告选项(运行macOS Sierra 10.12.3的Mac上的GCC 6.3.0)完全编译:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition -c tr47.c
$
此代码尚未运行。我已就这个CS50问题为其他人的变种编写了类似的功能。它不需要比那更复杂。