【问题标题】:How to know/limit static stack size in C program with GCC/Clang compiler? [duplicate]如何使用 GCC/Clang 编译器知道/限制 C 程序中的静态堆栈大小? [复制]
【发布时间】:2021-07-27 13:34:27
【问题描述】:

我正在编写一个嵌入式程序,它使用一个已知大小的静态有限堆栈区域(换句话说,我有 X 个字节用于堆栈,并且没有可以按需为我分配更多堆栈的覆盖操作系统)。我想在运行时避免错误,而是在构建时捕获它们 - 如果我在运行时不适合堆栈的某些函数块中错误地声明了太多变量,则可以得到一些指示。

鉴于我在我的程序中不使用递归调用,我能否在编译期间以某种方式知道我的所有局部变量在最深的函数调用路径上将占用多少堆栈空间?或者至少知道如果编译器不够聪明,无法在所有嵌套调用中分析我的变量在单个块(函数)中占用多少空间?

【问题讨论】:

  • 老派的方法是在从调试器重置时将整个堆栈区域设置为 0xAA 之类的值,然后让程序运行一段时间,确保激发所有用例。然后停止并检查内存中还有多远的 0xAA。这不是 100% 科学的、万无一失的方法,但在绝大多数情况下,在实践中都可以正常工作。
  • @Emoun 编译器如何跟踪中断?它是否以某种方式下载带有程序的动态分析器或什么?如果不是,那么该链接不是正确答案。似乎是一些幼稚的 PC 编程解决方案。虽然this answer 提出了与我在上面评论中所做的完全相同的方法。
  • @Lundin 在 OP 的问题中他没有提到需要跟踪中断,因此该链接回答了如何使用 GCC 获取堆栈使用的直接问题。它是一个嵌入式系统,所以我从 OP 的描述中假设他们的程序具有完全的控制权。但是,如果您需要考虑中断,您可以独立分析中断处理程序,只需添加数字即可。虽然还没有真正考虑过这一点,所以并不是说它会完美无缺。
  • @Emoun 设计完全没有中断的嵌入式系统是不可能的。我们希望尽可能避免它们,但至少可能仍然存在至少一个循环定时器中断和其他错误状态中断。

标签: c gcc stack embedded clang


【解决方案1】:

鉴于我在我的程序中不使用递归调用,我能否在编译期间以某种方式知道我的所有局部变量在最深的函数调用路径上将占用多少堆栈空间?

仅当您不使用中断时。这在任何嵌入式系统中都极有可能。因此,您必须通过动态分析找出堆栈的使用情况。

老派的方法是在从调试器重置时将整个堆栈区域设置为 0xAA 之类的值,然后让程序运行一段时间,确保激发所有用例。然后停止并检查内存中还有多远的 0xAA。这不是一种 100% 科学的、万无一失的方法,但在绝大多数情况下,在实践中都可以正常工作。

其他方法包括在您不希望程序结束的某些堆栈位置设置写断点,有点像“硬件堆栈金丝雀”。运行程序并确保断点永远不会触发。如果是,则从那里进行调查,将断点进一步向下移动到内存映射以查看确切的位置。

另一个好的做法是始终对堆栈进行内存映射,以便它只能溢出到禁止的内存或至少溢出到只读闪存等 - 理想情况下,你会得到堆栈溢出的硬件异常。您绝对希望避免堆栈溢出到 .data/.bss 等其他 RAM 部分,因为这会导致严重且极其微妙的错误情况。

【讨论】:

    猜你喜欢
    • 2019-09-17
    • 2019-07-16
    • 2021-03-08
    • 1970-01-01
    • 2011-10-02
    • 2012-08-25
    • 2014-03-12
    • 2018-02-08
    相关资源
    最近更新 更多