一种计算堆栈大小的方法

时间:2014-10-13 09:39:02

标签: c compilation stack linkage

我认为这个问题与编译/链接有关,而不是与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;
}

除了在代码段和数据段之后堆栈位于的明显情况之外,此方法中还存在其他可能的空洞?

是否有可能一个或多个部分没有从我期待的地方开始?

由于

2 个答案:

答案 0 :(得分:2)

在现代计算机中,没有好的方法来确定最大堆栈大小。例如,许多操作系统使用虚拟内存系统使堆栈以随机(但高)地址开始。出于安全原因,它是随机的。如果你有一个64位系统,你有比实际RAM多数百万甚至数十亿的地址,所以堆栈的开头几乎没有告诉你什么。我甚至看到了堆栈增长到更大地址的系统(HP-UX)。

同样适用于可以在任何地方的代码段(现在通常是安全性)。

最后,您有多个全局数据段。在许多C实现中,您至少有一个初始化和一个未初始化的全局段。但是我看到编译器出于各种原因创建了更多的段。

这个问题包含更多令人讨厌的细节,但也包含一些解决方案:Checking available stack size in C

答案 1 :(得分:1)

我不知道这是如何开始成为一种明智的做法。除其他外,它假设

  • 堆栈和全局/代码紧挨着彼此,
  • 之间没有其他内容
  • 堆栈从分配给它的区域的“正确”端开始,分别以正确的方向增长
  • 使用codeAddr时,它会假定&main点位于“代码”段的开头/结尾;即使您只定义main,默认情况下也会链接许多其他代码。
  • 使用dataAddr时,它会假定&global点位于“数据”细分的开头/结尾;即使您只定义了这个变量,标准库也会定义一些变量。

没有充分的理由去承担这些事情。而且,完全没必要。有可靠的机制来查找堆栈大小,虽然它们是特定于操作系统的,但它们至少可以在运行该操作系统的不同架构之间移植,并且如果满足所有假设,它们不会受到您的方法会产生的许多微小不准确性的影响。 (例如,堆栈内存的“末尾”通常有几个不可用的页面。)

更不用说开始关注堆栈大小的理由很少。