Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unload()递归C Segfault(类似TRIE的数据库)CS50 pset5_C_Dictionary_Recursion_Trie_Cs50 - Fatal编程技术网

Unload()递归C Segfault(类似TRIE的数据库)CS50 pset5

Unload()递归C Segfault(类似TRIE的数据库)CS50 pset5,c,dictionary,recursion,trie,cs50,C,Dictionary,Recursion,Trie,Cs50,编辑1 正如我所建议的,我现在不使用以下划线开头的名称,也不使用在-> \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu强 当试图用递归函数释放struct时,我遇到了一个segfault 这是我的结构: //creating new trie data ctructure typedef

编辑1
正如我所建议的,我现在不使用以下划线开头的名称,也不使用在
->

\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu强

当试图用递归函数释放struct时,我遇到了一个segfault

这是我的结构:

//creating new trie data ctructure
typedef struct dict
{
    bool is_word;
    struct dict *children[ALPHABET+1];
}
node;
它用于存储字典,字典用于拼写检查。在程序结束时,我需要释放所有分配的内存

这是我写的函数。它应该称自己是自由的,一块一块地释放。然而,在多次调用自己之后,它给了我segfault

 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;
 }
bool卸载(无效)
{
//检查是否为根
if(temp==根)
{
对于(int i=0;ichildren[i]&&i!=字母表)
{
}
如果(!temp->children[i]&&i==字母表),则为else
{
免费(临时);
返回true;
}
否则如果(临时->儿童[i])
{
temp=temp->children[i];
卸载();
}
}
}
其他的
{
对于(int i=0;ichildren[i]&&i!=字母表)
{
}
如果(!temp->children[i]&&i==字母表),则为else
{
temp1=temp;
temp->children[i]=temp;
免费(temp1);
返回true;
}
否则如果(临时->儿童[i])
{
temp=temp->children[i];
卸载();
}
}
}
返回false;
}

假设root、temp、temp1是全局的。它们都是struct dict.当函数第一次被调用时,temp==root。

您的代码正在演示为什么全局变量是一个坏主意,而且会适得其反。您应该将要释放的节点传递给函数;初始调用传递根节点。函数不需要访问任何全局变量

还要注意的是,点
和箭头
->
运算符绑定得非常紧密,不应在其周围写任何空格。此外,以下划线开头的名称基本上保留供实现使用。比那还多,但不多。最简单的方法是避免在您发明的名称中使用下划线。仅用于访问系统提供的设施

此代码执行必要的操作,假设分配
节点的代码确保所有指针为空

#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);
}

此代码尚未运行。我已经为其他人在CS50问题上的变体编写了类似的函数。不需要比这更复杂。

欢迎使用堆栈溢出。请尽快阅读和页面,但更重要的是,请阅读如何创建MCVE()。这里MCVE的关键要求之一是触发问题的一组紧凑的输入值。那好像不见了。非常感谢你的建议!我希望现在更好?您的代码正在演示为什么全局变量是个坏主意,而且会适得其反。您应该将要释放的节点传递给函数;初始调用传递根节点。该函数不需要访问任何全局变量。实际上,根据赋值,我不应该更改卸载声明(即
bool unload(void)
),这就是使用全局变量的原因。节点分配部分如下所示:node*getnode(void){node*newnode=malloc(sizeof(node));if(newnode!=NULL){newnode->is_word=false;for(int i=0;i<(ALPHABET+1);i++)newnode->children[i]=NULL;}return newnode;}确定:写入:
bool unload(void){real\u unload(root);返回true;}
并将我编写的函数重命名为
real\u unload()
。或者可以使用:
bool unload(void){if(root==NULL)返回false;real_unload(root);返回true;}
。不要创建名为
temp
的全局变量。使用globals的时间不要过长。干净利落地完成工作-如图所示。不要告诉我-除了指定的函数外,您不允许编写其他函数?在这种情况下,你有一个虐待狂导师。这是CS50;你确定你引用的规则吗?以前没有人抱怨过类似的释放代码,但是……不,只是我不能更改特定函数的实现(比如卸载)。我们可以自由编写任何我们认为有用的函数。所以我会记住你的这个把戏!
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
>     -Wstrict-prototypes -Wold-style-definition -c tr47.c
$