我在C中有两个版本的代码。
版本1:
#include <unistd.h>
#include <stdio.h>
int globalA = 10000;
int globalB = 0;
int recursion(int *a, int *b)
{
*a = *a - 1;
*b += *a;
if (*a < 1) {
sleep(30);
return *b;
} else {
return recursion(a, b);
}
}
int main()
{
printf("globalA: %i\n", globalA);
printf("globalB: %i\n", globalB);
recursion(&globalA, &globalB);
printf("globalA: %i\n", globalA);
printf("globalB: %i\n", globalB);
return 0;
}
和版本2 - 相同的代码,但没有指针:
#include <unistd.h>
#include <stdio.h>
int globalA = 10000;
int globalB = 0;
int recursion(int a, int b)
{
a = a - 1;
b += a;
if (a < 1) {
sleep(30);
return b;
} else {
return recursion(a, b);
}
}
int main()
{
printf("globalA: %i\n", globalA);
printf("globalB: %i\n", globalB);
recursion(globalA, globalB);
printf("globalA: %i\n", globalA);
printf("globalB: %i\n", globalB);
return 0;
}
当代码在第12行时,我在os x上调用console command vmmap - sleep(30);
我的问题是为什么vmmap为第一个版本显示此行的堆栈:
VIRTUAL RESIDENT DIRTY SWAPPED VOLATILE NONVOL EMPTY REGION
REGION TYPE SIZE SIZE SIZE SIZE SIZE SIZE SIZE COUNT (non-coalesced)
=========== ======= ======== ===== ======= ======== ====== ===== =======
Stack 8192K 476K 476K 0K 0K 0K 0K 2
和第二个版本:
Stack 8192K 316K 316K 0K 0K 0K 0K 2
因此,版本1的堆栈的常驻大小比版本2更大。
我认为在版本2中,每次递归调用都会在每个新的堆栈帧中创建变量 a 和 b 的新副本。因此,每次调用递归时,它将在堆栈中消耗更多内存。
在版本1中,不需要创建变量 a 和 b 的新副本,因为它们是通过引用传递的,并且通过引用给出的变量是全局的,因此 globalA 必须位于 .data内存段中, .bss段中的 globalB 。因此,堆栈中所需的空间更少。
我错了吗?请向我解释这里的诀窍。
P.S。代码是用clang编译的
答案 0 :(得分:5)
在&#34;全局&#34;例如,您不必为每次递归在堆栈上创建变量globalA
和globalB
的新副本,但是做仍然需要创建新副本每个递归的堆栈上指针变量a
和b
的值。您不会说出您正在使用的操作系统或ABI,但我希望sizeof(int *)
大于sizeof(int)
。