【问题标题】:Change stack size for a C++ application in Linux during compilation with GNU compiler在使用 GNU 编译器编译期间更改 Linux 中 C++ 应用程序的堆栈大小
【发布时间】:2011-01-17 13:08:33
【问题描述】:

在 OSX 中使用 g++ 编译 C++ 程序时,我使用

LD_FLAGS= -Wl,-stack_size,0x100000000

但在 SUSE Linux 中,我经常收到如下错误:

x86_64-suse-linux/bin/ld: unrecognized option '--stack'

和类似的。

我知道可以使用

ulimit -s unlimited

但这并不好,因为单个用户并不总是可以做到这一点。

如何使用 GCC 在 Linux 中为单个应用程序增加堆栈大小?

【问题讨论】:

  • 如果有帮助:2.6.18.8-0.9-default #1 SMP Sun Feb 10 22:48:05 UTC 2008 x86_64 x86_64 x86_64 GNU/Linux
  • gcc --ver: gcc 版本 4.1.2 20061115 (prerelease) (SUSE Linux)
  • 尝试在Stack Clash 修正后设置rlimit_stack 可能会导致失败或相关问题。另请参阅红帽 Issue 1463241
  • ld -v,请

标签: gcc gnu


【解决方案1】:

您可以使用setrlimit 以编程方式设置堆栈大小,例如

#include <sys/resource.h>

int main (int argc, char **argv)
{
    const rlim_t kStackSize = 16 * 1024 * 1024;   // min stack size = 16 MB
    struct rlimit rl;
    int result;

    result = getrlimit(RLIMIT_STACK, &rl);
    if (result == 0)
    {
        if (rl.rlim_cur < kStackSize)
        {
            rl.rlim_cur = kStackSize;
            result = setrlimit(RLIMIT_STACK, &rl);
            if (result != 0)
            {
                fprintf(stderr, "setrlimit returned result = %d\n", result);
            }
        }
    }

    // ...

    return 0;
}

注意:即使使用这种方法来增加堆栈大小,您也不应该在main() 本身中声明大的局部变量,因为在getrlimit/ 之前输入main() 很可能会发生堆栈溢出setrlimit 代码有机会更改堆栈大小。因此,任何大的局部变量都应该只在堆栈大小成功增加后从main() 调用的函数中定义。

【讨论】:

  • 确保您的操作系统具有正确的 #include ,例如对于 Mac OS X,它将是 #include &lt;sys/resource.h&gt;
  • 我在 SLES 11 上尝试过。即使设置了值,我也无法根据新限制定义局部变量 --> segmentation fault。只有当我在命令行ulimit -s 16000 中运行时,我才能定义像char x [14000000] 这样的局部变量。显然堆栈大小不是通过此代码设置的。有什么想法吗?
  • @AlBundy:我只能告诉你,上面的代码在 OS X 和各种 Linux 版本上都适用于我。不过,我想到了一个想法:您是否要在 main() 本身中声明一个大型局部变量?这当然行不通,因为在到达getrlimit/setrlimit 代码之前,您就会发生堆栈溢出。将大局部变量放在另一个函数中,然后从main(在getrlimit/setrlimit 代码之后)调用此函数。
  • @PaulR:好的。我在main() 中尝试过,但之后我设置了新的限制。显然这不起作用。当我从main() 调用一个具有巨大局部变量的函数时,它就可以工作了。我现在用不同的限制检查了它,一切都很完美。结论:堆栈限制必须在main() 中设置,以便对程序的其余部分有效。我还不得不关闭 ssh 会话,因为我在玩 ulimit -s 并且我总是得到 -1 作为返回码。
  • 感谢您的确认 - 我现在在答案中添加了注释,以防其他人遇到同样的问题。
【解决方案2】:

代替stack_size,使用--stack,如下所示:

gcc -Wl,--stack,4194304 -o program program.c

这个例子应该给你 4 MB 的堆栈空间。适用于 MinGW 的 GCC,但正如手册页所述,“此选项特定于链接器的 i386 PE 目标端口”(即仅适用于输出 Windows 二进制文件)。似乎没有 ELF 二进制文件的选项。

【讨论】:

  • 不幸的是,我尝试了这个但它不起作用:/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse -linux/bin/ld:无法识别的选项“--stack”/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/bin /ld:使用 --help 选项获取使用信息 collect2:ld 返回 1 个退出状态
  • 是的,编辑了我的答案,因为我注意到它不适用于 ELF 输出。抱歉,我在这里帮不上什么忙。
  • 好吧,你救了我。我在窗户上;)。谢谢!
  • 在 CMake 中,有 a few commands 设置了这个选项,这在 Windows 上都对我有用。
【解决方案3】:

这是一个老话题,但这里回答的所有标志都不适合我。无论如何,我发现-Wl,-z,stack-size=4194304(例如 4MB)似乎可以工作。

【讨论】:

    【解决方案4】:

    考虑使用-fsplit-stack选项https://gcc.gnu.org/wiki/SplitStacks

    【讨论】:

    • -fsplit-stack 将我的用例的性能降低了约 20%。
    • 嗨@Dennis,考虑将此性能与堆的使用进行比较。
    【解决方案5】:

    使用 ulimit bash 内置函数或 setrlimit() 或在登录时更改它 使用 PAM (pam_limits.so)。

    这是一个可设置的 用户资源限制;请参阅 setrlimit(2) 中的 RLIMIT_STACK。

    http://bytes.com/topic/c/answers/221976-enlarge-stack-size-gcc

    【讨论】:

    • 正如我所说,我不能这样做,我还必须将此应用程序提供给其他不应该使用此技巧的用户
    • 你不明白:对setrlimit的调用可以在你的C++代码中完成,在main的开头。
    猜你喜欢
    • 2010-10-15
    • 2019-07-16
    • 2015-07-08
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    相关资源
    最近更新 更多