当变量超出范围时,有没有办法强制 gcc 从堆栈中释放空间

Is there a way for force gcc to free the space from the stack when variables go out of scope

提问人:Louis Caron 提问时间:9/13/2022 最后编辑:phuclvLouis Caron 更新时间:7/10/2023 访问量:172

问:

我有以下一段代码:

extern void func1(char *array);
extern void func2(char *array);

void myfunction(void) {
    if (somecondition) {
        char var2[256];
        func2(var2);
    }
    if (someothercondition) {
    {
        char var3[3];
        func3(var3);
    }
}

我无法让我的编译器 (gcc) 调用堆栈中仅用于 3 个字节。它始终为调用范围内使用的空间分配空间,即使此变量超出范围并且可以安全地从堆栈中删除。func3var3var2func2

我尝试了在 gcc 文档中找到的几个选项:

  • fomit-frame-pointer
  • fconserve-stack

我已经在 x86 和 ARM 架构上尝试过了,它的行为相同。

这个问题背后的基本原理是仅使用必要的堆栈大小。

而相关的问题:如果可以优化堆栈空间,是否可以在选项生成的 .su 文件中添加用于每个子函数调用的堆栈。-fstack-usage

谢谢

c GCC 堆栈分配

评论

4赞 user3386109 9/13/2022
它不是那样工作的。堆栈空间在函数序言中分配一次,在函数尾声中释放一次。这不像堆栈指针在变量进出范围时被捶打。您可以使用该函数自行管理堆栈空间。alloca
3赞 Eric Postpischil 9/13/2022
@user3386109:Re “It doesn't work that way.”:GCC 可能不是那样操作的,但它不是 C 标准强制要求的,编译器可以逐块分配堆栈空间,而不是按函数分配堆栈空间。
2赞 Eric Postpischil 9/13/2022
请注意,通常使用的堆栈空间对程序的影响很小或没有影响,除非它超出了堆栈限制,或者存在一些影响性能的其他交互。除非在许多函数调用(不同函数或同一函数的递归调用)中减少堆栈的使用,否则不太可能看到相当大的好处。为什么要减少此函数中的堆栈使用?
2赞 Louis Caron 9/13/2022
@EricPostpischil:是的,我正在努力解决堆栈溢出的问题,如果堆栈在编写代码时实际使用(变量的范围有限等),则不应该发生堆栈溢出。在我的真实示例中,我有一个需要 4kB RAM 的块和另一个需要 4kB 的块中的子函数,这两个块相加而不是共享空间。我有一个只有 256kB RAM 的微控制器。
1赞 Louis Caron 9/13/2022
@user3386109:很遗憾,我不能真正分享代码,但它与我创建的代码非常相似。实际上,我想为大家发布一个问题的答案:解释为什么这是不可能的(文档)并展示可能的机制(使用函数)。您是否有指向文档的链接,说明堆栈在序言中仅分配一次?谢谢

答:

1赞 anton-tchekov 7/10/2023 #1

你可以做这样的事情:

extern void func1(char *array);
extern void func2(char *array);

void _helper(/* neccessary parameters */)
{
    char var2[256];
    func2(var2);
}

void myfunction(void) {
    if (somecondition) {
        _helper(/* neccessary parameters */);
    }
    if (someothercondition) {
    {
        char var3[3];
        func3(var3);
    }
}

由于分配发生在不同的函数中,因此编译器只会在调用 时分配内存。这可能容易受到优化(内联)的影响,但将帮助程序移动到不同的编译单元(新的 c 文件)将阻止这种情况。_helper

当然,这将是以函数调用和参数复制为代价的。

无论如何,如果堆栈空间问题与递归有关,则应考虑将其替换为使用显式预分配堆栈的迭代解决方案。

评论

0赞 Louis Caron 7/10/2023
这是我想出的解决方案,但由于我的代码是由闭源商业工具自动生成的,因此我无法修改它。我一直在寻找一个编译器选项来允许这种优化。