内存分配的递归

时间:2015-10-07 15:09:47

标签: c recursion memory-management heap

我正在观看一个关于CUDA和Barnes-Hut算法的视频,其中声称有必要对GPU的树放置一个深度限制,然后我想到了可能在递归中的想法。堆。

基本上,我想知道:是否可以从堆中分配内存并将其用作临时堆栈"在哪里放置函数调用有问题的递归函数有点延迟堆栈溢出?

如果是这样,它是如何实现的,我们是否会为指向函数的指针分配空间?我认为它会涉及在堆中存储函数地址,但我不太确定。

[edit]我只是想补充说这纯粹是一个理论问题,我想这样做会导致程序在使用堆时减速。

[edit]根据请求,我使用的编译器是Ubuntu 14.04(64位)上的GCC 4.8.4

2 个答案:

答案 0 :(得分:3)

不确定。这称为延续传递方式。标准库支持setjmp()longjmp(),并将恢复控制所需的信息存储到名为jmp_buf的结构中的较早点。 (对于可以从中恢复的位置有几个限制。)您可以将它们存储在堆栈中,这只是一个LIFO队列。

更通用的方法是将程序作为状态机运行,并在称为trampoline的数据结构中存储回溯程序状态所需的信息,称为延续。想要这样做的一个常见原因是在不优化它的实现中获得等效的尾递归,并且可能会占用大量的堆栈空间。一个真实世界的应用程序,我认识的人正在编写一个蹦床是一个GLL解析器,其中语法表示为有向图,解析的结果是一个共享的打包解析林,解析器经常需要回溯尝试不同的规则。

延续传递和蹦床似乎被认为是一种奇特的风格,因为它们来自功能编程世界,而longjmp()被视为丑陋的低级黑客,甚至Linux手册页也说不使用它

答案 1 :(得分:1)

您可以通过将自己的基于堆的堆栈实现为结构数组来模拟这一点,每个结构表示一个堆栈框架,其中包含等效的参数和局部变量。函数循环并且每个调用"而不是递归调用自身的函数。显式地将一个新帧推入堆栈。

我在尝试解决一个简单的棋盘游戏时完成了这几年。该程序最初是递归的,它需要永远运行。我将其更改为上述结构,这使得应用程序可中断/可重启变得简单。当被打断时,应用程序将其"堆栈"到州文件。重新启动时,应用程序加载了状态文件并继续停止。

如果堆栈帧结构包含嵌入式指针,这确实需要注意,但它并非不可克服。