在使用内存方面,用户定义的堆栈和内置的堆栈有什么区别?
What is the difference between user defined stack and built in stack in use of memory?
我想使用用户定义的堆栈为我的程序有大量的递归调用?定义用户定义的堆栈有用吗?
有几种方法可以做到这一点。
主要、两个:
(1)使用CPU/处理器堆栈。有一些变体,每个都有自己的局限性。
(2)或者,重新编码你的函数,使用一个模拟"堆栈"的"堆栈帧"结构体。实际的函数不再是递归的。这实际上可以是无限的,直到堆允许
For(1)…
(A)如果您的系统允许,您可以发出syscall
来扩展进程的堆栈大小。这可能会限制您执行此操作的数量,并与共享库地址发生冲突。
(B)你可以malloc
一个大的区域。使用一些[有点]复杂的内联asm技巧,您可以将该区域交换为堆栈[并再次返回],并将此malloc
区域作为堆栈调用函数。可行,但不适合胆小的人……
(C)更简单的方法是大面积malloc
。将该区域传递给pthread_attr_setstack
。然后,使用pthread_create
将递归函数作为线程运行。注意,你并不真正关心多线程,它只是一种简单的方法来避免asm的"混乱"把戏。
对于(A), 假设堆栈扩展系统调用允许,限制可能是堆栈允许的所有可用内存[不超过某个系统范围或RLIMIT_*参数]。
对于(B)和(C),您必须在开始之前"猜测"并使malloc
足够大。完成后,大小是固定的,并且可以进一步扩展而不是。
事实上,这并不完全正确。重复使用asm技巧[当需要时],你可以模拟一个接近无限的堆栈。但是,在我看来,跟踪这些大型malloc区域的开销足够高,我选择下面的(2)。
For(2)…
可以根据需要扩展/收缩。其中一个优点是,您不需要事先猜测需要多少内存。[伪]堆栈可以根据需要继续增长[直到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 memoryn");
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;
}
所有的函数、对象、变量和用户定义结构都使用由操作系统和编译器控制的内存空间。所以,这意味着你定义的堆栈在一个通用的内存空间下工作,这个内存空间是为你的进程的堆栈在OS中指定的。因此,它没有太大的区别,但是您可以定义一个高效的优化结构来更好地使用这个通用堆栈。
- 内置函数可查看CPP中的成员变量
- 是否有内置方法可以强制转换为不同的基础类型,但保留常量限定符?
- 按字母顺序对字符串中的字母进行排序,而无需使用内置的 sort()
- 将字符串转换为浮点数或整数,而无需使用内置函数(如 atoi 或 atof)
- 如何从 c++ 中类中内置的数组继承
- 如何捕获 C++ 内置异常对象
- macOS 是内置在 clang 编译器中还是内置于 xcode ide 中?
- 将编译器开关添加到 Eclipse CDT 内置编译器设置生成?
- gcc Atomic在gcc 4.1.1中内置了奇怪的行为
- 是否有用于元素部分移位的 simd 指令/内在/内置指令?
- 何时包含内置类型和运算符的标头?
- 基本类型与内置类型有什么区别C++
- 指内置类型的文字
- GLUT 问题:重新声明 c++ 内置类型'wchar_t'时出错
- 像自定义类一样构造的指针(内置类型)如何工作?
- 内置类型与用户定义的类型 C++
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- C++内置类型的基于类型的调度
- 如何在 c++ 中将内置堆栈作为对递归函数的引用传递
- 在使用内存方面,用户定义的堆栈和内置的堆栈有什么区别?