Recursion 较大尝试的递归释放
我已经编写了一个基本函数,用于在C中递归地释放trie数据结构:Recursion 较大尝试的递归释放,recursion,memory,memory-management,segmentation-fault,trie,Recursion,Memory,Memory Management,Segmentation Fault,Trie,我已经编写了一个基本函数,用于在C中递归地释放trie数据结构: // Root pointer is passed as arg in initial call void destroy(node *trav) { for (int i = 0; i < N; i++) { if (trav->children[i]) { destroy(trav->children[i]); }
// Root pointer is passed as arg in initial call
void destroy(node *trav)
{
for (int i = 0; i < N; i++)
{
if (trav->children[i])
{
destroy(trav->children[i]);
}
}
free(trav);
}
//根指针在初始调用中作为arg传递
无效销毁(节点*trav)
{
对于(int i=0;ichildren[i])
{
销毁(trav->儿童[i]);
}
}
免费(trav);
}
对于任何较小的字典文件,该函数似乎都可以很好地工作。程序成功加载和卸载的最大文件包含134480个字
但是,在释放较大的trie时,它会产生分段错误。导致分段错误的较大文件包含506915个字
Valgrind生成的错误消息指出:“大小为8的无效读取”,然后是几个回溯,最后是;“地址不是堆栈、malloc或(最近)空闲”
这可能是什么原因造成的
这可能是什么原因造成的
堆栈溢出可能是造成这种情况的原因,尽管这似乎不太可能:几乎没有局部变量,因此每个帧可能只消耗32字节的堆栈,这将允许使用Linux默认8MiB堆栈进行8M/32==262144级的递归
但是,如果您的trie极不平衡,则可能会出现堆栈溢出
您可以尝试ulimit-s unlimited
,看看这是否能解决问题
或者您可以在GDB下运行程序,并检查报告
SIGSEGV
的指令。如果是调用
,推送
,或另一种形式的“移动到堆栈”,堆栈溢出也很可能发生。我的资源限制已设置为最大值。如何使用GDB来识别分段错误的原因?它只是说,当我通过GDB运行程序时,程序收到了信号SIGSEGV。@GabrielSaulGDB--args/path/to/exe arg1…
。你可能还想读一读作为介绍——它会很好地打断你。非常抱歉。结果是我的一个缓冲区变量不够大,无法处理某个字符串。谢谢你的资源@GabrielSaul您应该考虑使用address sanitizer()构建您的程序——很可能这并不是这种类型的唯一错误,即使是,使用-fsanize=address
进行测试也是一个非常好的习惯。