Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ UNIX:UNIX中的堆栈大小(ulimit-s)应该是多少?_C++_C_Multithreading_Unix - Fatal编程技术网

C++ UNIX:UNIX中的堆栈大小(ulimit-s)应该是多少?

C++ UNIX:UNIX中的堆栈大小(ulimit-s)应该是多少?,c++,c,multithreading,unix,C++,C,Multithreading,Unix,如何在UNIX中计算程序所需的最小堆栈大小,使程序永远不会崩溃 假设我的程序是 int main() { int number; number++; return 0; } 1) 此程序运行所需的堆栈大小是多少?如何计算 2) 我的Unix系统提供了ulimit-s 512000。我的小程序真的需要这个值吗 3) 如果我有一个具有多线程的大程序,大约500个函数,包括一些库、宏、动态分配的内存等,那么需要多少堆栈大小呢?没有神奇的方法可以告

如何在UNIX中计算程序所需的最小堆栈大小,使程序永远不会崩溃

假设我的程序是

int main()
{
         int number;
         number++;
         return 0;
}
1) 此程序运行所需的堆栈大小是多少?如何计算

2) 我的Unix系统提供了
ulimit-s 512000
。我的小程序真的需要这个值吗


3) 如果我有一个具有多线程的大程序,大约500个函数,包括一些库、宏、动态分配的内存等,那么需要多少堆栈大小呢?

没有神奇的方法可以告诉你的程序在堆栈上需要多少空间。这取决于代码实际在做什么。无限(或非常深)递归将导致堆栈溢出,即使程序似乎什么也不做

作为示例,请参见以下内容:

$ ulimit
unlimited
$ echo "foo(){foo();} main(){foo();}" | gcc -x c -
$ ./a.out 
Segmentation fault (core dumped)
  • 您的程序本身使用了几个字节-1 int,但当然也要考虑运行时中位于
    main
    之前的部分。但它不太可能超过几十个字节,可能一次超过几百个字节。因为任何现代操作系统中的最小堆栈大小都是“一页”=4KB,这应该很容易适应
  • 51200=51.2MB,但这似乎相当高。在我的LinuxFedora16x86-64机器上,它是8192
  • 线程并不重要,因为每个线程都有自己的堆栈。函数的数量本身对堆栈的使用并不是一个很大的影响因素。堆栈耗尽几乎总是由大型局部变量和/或深度递归引起的。对于任何稍微复杂一点的程序来说,计算精确的堆栈使用率是相当棘手的。通常,它需要大量运行程序并查看堆栈是否“爆炸”。如果没有,则有足够的堆栈。一般来说,库函数往往不使用大量堆栈,但总会有例外 举例来说:

    void func()
    {
       int x, y, z;
       float w;
       ...
    }
    
    此函数占用大约16字节的堆栈,加上调用函数的一般开销,通常为1-3个“机器字”(32位机器上为4-12字节,64位机器上为8-24字节)


    此函数将占用40000字节的堆栈空间。显然,不需要对该函数进行多次递归调用就可以耗尽堆栈

    大多数人依赖于堆栈是“大”的,而他们的程序不使用所有堆栈,这仅仅是因为堆栈的大小设置得太大,以至于程序很少会因为堆栈空间不足而失败,除非他们使用具有自动存储持续时间的超大阵列

    这是一个工程故障,从某种意义上说,它不是工程故障:一个已知且基本上可以预防的完全故障源是不可控的

    通常,很难计算程序的实际堆栈需求。特别是当存在递归时,编译器通常无法预测一个例程将被递归调用多少次,因此它无法知道该例程将需要多少次堆栈空间。另一个复杂问题是对运行时准备的地址的调用,例如对虚拟函数的调用或通过其他函数指针的调用

    不过,编译器和链接器可以提供一些帮助。对于任何使用固定堆栈空间的例程,理论上,编译器都可以提供这些信息。一个例程可能包括执行或未执行的块,每个块可能有不同的堆栈空间要求。这会干扰编译器为例程提供固定的数字,但编译器可能会单独提供关于每个块的信息和/或例程的最大值

    理论上,链接器可以检查调用树,如果调用树是静态的且不是递归的,则可以为链接程序提供最大的堆栈使用量。它们还可以提供沿着特定调用子链的堆栈使用(例如,从一个例程到导致递归调用同一例程的调用链),这样人类就可以将算法知识应用到子链堆栈使用的倍数上,最大次数为递归调用子链的次数

    我没有见过具有这些功能的编译器或链接器。这表明,开发这些功能几乎没有经济动机

    有时堆栈使用信息很重要。操作系统内核可能有一个比用户进程更有限的堆栈,因此应该计算内核代码的最大堆栈使用量(作为一个良好的工程实践),以便可以适当地设置堆栈大小(或者重新设计代码以使用更少的堆栈)

    如果您有计算堆栈空间需求的关键需求,可以检查编译器生成的汇编代码。在许多计算平台上的许多例程中,在例程开始时从堆栈指针中减去一个固定数字。在没有附加减法或“推”指令的情况下,这是例程的堆栈使用,不包括它调用的子例程使用的其他堆栈。但是,例程可能包含包含额外堆栈分配的代码块,因此必须仔细检查生成的汇编代码,以确保找到所有堆栈调整

    例程还可能包含在运行时计算的堆栈分配。在计算堆栈空间非常关键的情况下,可以避免编写导致此类分配的代码(例如,避免使用C的可变长度数组特性)

    一旦确定了每个例程的堆栈使用情况,就可以通过沿各种例程调用路径添加每个例程的堆栈使用情况(包括调用
    main
    之前运行的启动例程的堆栈使用情况)来确定程序的总堆栈使用情况

    这种使用完整程序的堆栈计算通常比较困难,很少执行

    您通常可以估计堆栈的使用情况
    void func2()
    {
        int x[10000];
        ...
    }