2016-08-28 43 views

回答

0

所有的函数,对象,变量和用户定义的结构都使用由操作系统和编译器控制的内存空间。所以,这意味着您定义的堆栈在为您的OS中的进程堆栈指定的通用内存空间下工作。因此,它没有太大的区别,但是你可以定义一个高效率的优化结构来更好地使用这个通用堆栈。

3

有几种方法可以做到这一点。

首先,:

(1)使用CPU /处理器堆栈。有一些变体,每个都有其自身的限制。 (2)或者,重新编码您的函数以使用模拟“堆栈”的“堆栈帧”结构。实际的函数不再是递归的。这可能是几乎是无限高达无论堆将允许


对于(1)...

(A)如果您的系统允许,您可以发出syscall延长进程的堆栈大小。可以有多少限制可以做到这一点,并与共享库地址冲突。 (B)malloc大面积。有了一些[有点]错综复杂的内联asm欺骗,你可以将这个区域换成堆栈[并且再回来],并用这个malloc区域作为堆栈调用你的函数。可以,但不适合心灵的隐隐...

(C)更简单的方法是到malloc大面积。通过这个区域到pthread_attr_setstack。然后,使用pthread_create作为线程运行递归函数。请注意,你并不关心多线程,它只是避免“混乱”asm欺骗的一种简单方法。 (A),假设堆栈扩展了系统调用许可,限制可以是堆栈允许的所有可用存储器[高达某些系统范围或RLIMIT_ *参数]。 (B)和(C),在开始之前,您必须“猜测”并使malloc足够大。完成后,尺寸是固定的,可以进一步扩展而不是

其实这并不完全正确。反复使用asm技巧[需要时],可以模拟接近无限的堆栈。但是,国际海事组织,跟踪这些大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; 
}