如何使用 GCC/Clang 编译器知道/限制 C 程序中的静态堆栈大小?

时间:2021-05-05 08:30:13

标签: c gcc stack embedded clang

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

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

1 个答案:

答案 0 :(得分:3)

<块引用>

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

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

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

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

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

相关问题