【问题标题】:Is there a way to force gcc to start a new stack frame for a block?有没有办法强制 gcc 为一个块启动一个新的堆栈帧?
【发布时间】:2020-05-19 10:52:58
【问题描述】:

在 RAM 和堆栈空间有限的嵌入式 C++ 代码中,我经常遇到这种情况:

void f(parameters) {
  if (condition) g(...);   // g uses lots of stack space
  else {
    int table[1000];
    // do something involving table
  }
}

Gcc 在函数开始时在堆栈上为“table”分配空间,这意味着堆栈必须足够大以容纳“table”和 g() 所需的堆栈,即使它们在同一时间。

我想告诉 gcc 为包含 else 部分的 { } 块分配一个新的堆栈帧。这样,堆栈只需要足够大以容纳较大的“表”(加上 else 部分所需的其他堆栈)和调用 g() 所需的堆栈。有没有办法做到这一点?

我通常的解决方法是将 else 块转换为另一个函数调用并将该函数标记为不被内联;但在某些情况下,这样的解决方案很难看,因为该函数需要大量参数来传递之前在 f() 中计算的值。

【问题讨论】:

    标签: c++ gcc stack-frame


    【解决方案1】:

    您可以使用函数,同时要求编译器不要内联扩展它。

    但在某些情况下这样的解决方案是丑陋的,因为函数需要大量的参数来传递值

    将参数收集到单个类(或几个类)中以使其不那么难看。

    或者您可以隐式捕获 lambda 中的参数。 Lambda 确实引入了它自己的丑陋之处:

      if (condition) g(...);   // g uses lots of stack space
      else {
        [&]() {
          int table[1000];
          // do something involving table
        }();
      }
    

    如果动态存储是一个选项,则使用它来分配大小与堆栈大小相关的数组。

    【讨论】:

    • 那个 lambda 仍然被内联,需要__attribute__((noinline)) 来防止这种情况。见gcc.godbolt.org/z/xtwkhQ
    • 谢谢,我没想过使用 lambda。在这种情况下,动态分配不是一种选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 2018-11-07
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    相关资源
    最近更新 更多