我认为这个问题与编译/链接有关,而不是与C标准有关。
考虑以下计算堆栈大小的方法:
#define ORDER(a,b,c) ((a) <= (b) && (b) <= (c))
int global;
int main()
{
int local;
unsigned long long dataAddr = (unsigned long long)&global;
unsigned long long stackAddr = (unsigned long long)&local;
unsigned long long codeAddr = (unsigned long long)main;
if (ORDER(stackAddr,dataAddr,codeAddr) || ORDER(codeAddr,stackAddr,dataAddr))
printf("Stack size is %llu bytes\n",dataAddr-stackAddr);
else if (ORDER(stackAddr,codeAddr,dataAddr) || ORDER(dataAddr,stackAddr,codeAddr))
printf("Stack size is %llu bytes\n",codeAddr-stackAddr);
else
printf("Stack size cannot be computed with this method\n");
return 0;
}
除了在代码段和数据段之后堆栈位于的明显情况之外,此方法中还存在其他可能的空洞?
是否有可能一个或多个部分没有从我期待的地方开始?
由于
答案 0 :(得分:2)
在现代计算机中,没有好的方法来确定最大堆栈大小。例如,许多操作系统使用虚拟内存系统使堆栈以随机(但高)地址开始。出于安全原因,它是随机的。如果你有一个64位系统,你有比实际RAM多数百万甚至数十亿的地址,所以堆栈的开头几乎没有告诉你什么。我甚至看到了堆栈增长到更大地址的系统(HP-UX)。
同样适用于可以在任何地方的代码段(现在通常是安全性)。
最后,您有多个全局数据段。在许多C实现中,您至少有一个初始化和一个未初始化的全局段。但是我看到编译器出于各种原因创建了更多的段。
这个问题包含更多令人讨厌的细节,但也包含一些解决方案:Checking available stack size in C
答案 1 :(得分:1)
我不知道这是如何开始成为一种明智的做法。除其他外,它假设
codeAddr
时,它会假定&main
点位于“代码”段的开头/结尾;即使您只定义main
,默认情况下也会链接许多其他代码。dataAddr
时,它会假定&global
点位于“数据”细分的开头/结尾;即使您只定义了这个变量,标准库也会定义一些变量。没有充分的理由去承担这些事情。而且,完全没必要。有可靠的机制来查找堆栈大小,虽然它们是特定于操作系统的,但它们至少可以在运行该操作系统的不同架构之间移植,并且如果满足所有假设,它们不会受到您的方法会产生的许多微小不准确性的影响。 (例如,堆栈内存的“末尾”通常有几个不可用的页面。)
更不用说开始关注堆栈大小的理由很少。