堆栈限制和递归函数

时间:2018-04-14 02:38:51

标签: c recursion linux-kernel stack stack-overflow

C程序使用递归来查找图的属性。无法处理大图,因为堆栈空间太小。必须重新编码程序以使用显式堆栈和循环。

递归函数应该先检查输入是否“适合”堆栈空间?

Linux内核中是否有一个示例,其中递归函数必须用'explicit'递归替换?

1 个答案:

答案 0 :(得分:1)

  

如果递归函数检查输入将" fit"在堆栈空间   第一λ

这通常非常困难。当使用不同的编译器或相同编译器的不同版本编译代码或使用不同的编译器开关来编译代码时,每个递归调用所需的堆栈内存量可能不同。事实上,根据控制流程的不同,该函数可能需要在不同的调用中使用不同数量的堆栈内存。

因此,如果您认为存在溢出堆栈的严重风险,则应将递归转换为迭代(可能使用显式堆栈)和/或限制递归/迭代次数。

  

Linux内核中是否存在递归函数的示例   将被替换为' explicit'递归?

是。一个很好的例子就是实现符号链接解析的代码。 Prior to Linux 4.2,代码递归如下:

link_path_walk -> nested_symlink -> follow_link -> link_path_walk

link_path_walk是主要的名称解析功能。如果它检测到符号链接,则会调用nested_symlink,然后可以递归调用link_path_walk。为了减轻内核中的堆栈溢出,nested_symlink执行以下检查:

if (unlikely(current->link_count >= MAX_NESTED_LINKS)) {
    path_put_conditional(path, nd);
    path_put(&nd->path);
    return -ELOOP;
}

每个任务描述符都有一个link_count字段,每次调用nested_symlink时都会增加该字段。如果超过固定阈值(Linux 4.1.51中MAX_NESTED_LINKS为8),则整个操作将以错误终止。

从Linux 4.2开始,递归代码被更改为具有显式堆栈的迭代代码,并且阈值被放宽到40.这个article详细讨论了迭代代码。