我想为我的程序使用用户定义的堆栈,它有大量的递归调用?定义用户定义的堆栈会有用吗?
答案 0 :(得分:4)
有几种方法可以做到这一点。
主要是两个:
(1)使用CPU /处理器堆栈。有一些变体,每个变体都有其自身的局限性。
(2)或者,重新编码您的函数以使用模拟“堆栈”的“堆栈框架”结构。实际的功能不再是递归的。无论堆允许什么,这几乎都是无限的
对于(1)......
(A)如果您的系统允许,您可以发出syscall
来扩展进程的堆栈大小。可能会限制您可以执行此操作以及与共享库地址冲突。
(B)你可以malloc
大片区域。使用某些[某种]错综复杂的内联asm技巧,您可以将此区域交换为堆栈[并再次返回]并使用此malloc
区域作为堆栈调用您的函数。可行,但不适合胆小的人......
(C)更简单的方法是malloc
大面积。将此区域传递给pthread_attr_setstack
。然后,使用pthread_create
将递归函数作为线程运行。注意,你并不真正关心多线程,它只是一种避免“凌乱”asm技巧的简单方法。
使用(A),假设堆栈扩展系统调用许可,限制可以是堆栈允许的所有可用内存[达到某个系统范围或RLIMIT_ *参数]。
使用(B)和(C),您必须“猜测”并在开始之前使malloc
足够大。完成后,大小是固定的,不可以进一步扩展。
实际上,这并不完全正确。重复使用asm技巧[需要时],你可以模拟近乎无限的堆栈。但是,IMO,跟踪这些大型malloc区域的开销足够高,我选择下面的(2)。
对于(2)......
这可以根据需要逐字扩展/收缩。其中一个优点是您不需要事先猜测您需要多少内存。 [pseudo]堆栈可以根据需要继续增长[直到malloc
返回NULL
: - )]。
这是一个递归函数示例[松散地处理为伪代码]:
int
myfunc(int a,int b,int c,int d)
{
int ret;
// do some stuff ...
if (must_recurse)
ret = myfunc(a + 5,b + 7,c - 6,d + 8);
else
ret = 0;
return ret;
}
这个函数改为使用struct
作为堆栈框架[再次,松散的伪代码]:
typedef struct stack_frame frame_t;
struct stack_frame {
frame_t *prev;
int a;
int b;
int c;
int d;
};
stack_t *free_pool;
#define GROWCOUNT 1000
frame_t *
frame_push(frame_t *prev)
{
frame_t *cur;
// NOTE: we can maintain a free pool ...
while (1) {
cur = free_pool;
if (cur != NULL) {
free_pool = cur->prev;
break;
}
// refill free pool from heap ...
free_pool = calloc(GROWCOUNT,sizeof(stack_t));
if (free_pool == NULL) {
printf("frame_push: no memory\n");
exit(1);
}
cur = free_pool;
for (int count = GROWCOUNT; count > 0; --count, ++cur)
cur->prev = cur + 1;
cur->prev = NULL;
}
if (prev != NULL) {
*cur = *prev;
cur->prev = prev;
cur->a += 5;
cur->b += 7;
cur->c += 6;
cur->d += 8;
}
else
memset(cur,0,sizeof(frame_t));
return cur;
}
frame_t *
frame_pop(frame_t *cur)
{
frame_t *prev;
prev = cur->prev;
cur->prev = free_pool;
free_pool = cur;
return prev;
}
int
myfunc(void)
{
int ret;
stack_t *cur;
cur = frame_push(NULL);
// set initial conditions in cur...
while (1) {
// do stuff ...
if (must_recurse) {
cur = frame_push(cur);
must_recurse = 0;
continue;
}
// pop stack
cur = frame_pop(cur);
if (cur == NULL)
break;
}
return ret;
}
答案 1 :(得分:0)
所有函数,对象,变量和用户定义的结构都使用由OS和编译器控制的内存空间。因此,这意味着您定义的堆栈在一般内存空间下工作,该内存空间是为OS中的进程堆栈指定的。因此,它没有太大的区别,但您可以更高效地定义优化结构,以便更好地使用这种通用堆栈。