如何在 运行 时间内使用 C 查找微控制器中的堆栈溢出

How to Find Stack Overflow in Microcontrollers using C in Run Time

我正在 STM32 微控制器上创建应用程序。我正在使用一些库堆栈。在那个堆栈之上,我正在使用我的应用程序。我有两个问题:

  1. 如何在运行时检测和处理堆栈溢出。因为我不知道那个库占用了多少内存。

  2. 如果我从头开始开发代码,如何在运行时检测和处理堆栈溢出。我读了一些我们必须为每个声明保留一些计数的地方。这是找到它的正确方法还是任何标准方法。

如果您的软件不是很小,我会首先尝试在您的笔记本电脑或台式机或平板电脑上调试大部分软件(可能 运行 Linux,因为它有很好的工具并且非常符合标准编译器,类似于您正在使用的交叉编译器)。然后,您可以从 valgrind or GCC 编译选项 -Wall -Wextra -g -fsanitize=address 等工具中获益....

您可以在 main 函数的开头存储堆栈顶部的近似值(例如,通过在 main 函数的开头执行 extern int* start_top_of_stack; 然后 int i=0; start_top_of_stack= &i; . 然后你可以在几个函数中有一些本地 int j=0; 并在它们开始时检查 &j - start_top_of_stack 不是太大。

但是有no silver bullet。我只是建议一个技巧。

如果您的应用程序对于接受昂贵的开发工作至关重要,您可以使用一些 formal method & source static program analysis tools (e.g. Frama-C, or make your own using MELT). If you are cross-compiling with a recent GCC 您可能想要使用 -Wstack-usage= 一些长度 and/or -fstack-usage 检查每个调用帧是否太大,或者手动计算所需的堆栈深度。

如果您受限于您的设备并且没有 "high sophisticated" 可用的工具,您至少可以尝试 "the old way"。一个简单的堆栈守卫可能会有所帮助。在你的代码中的某处(取决于你使用的工具),必须有堆栈区域的定义。类似于:

.equ         stacksize, 1024

stack:       .space   stacksize,0

(gnu 作为语法,你的可能不同)

使用您设备的启动代码将堆栈寄存器初始化到 stack 区域的顶部地址。

堆栈守卫然后只需将 "magic number" 添加到堆栈顶部和底部:

.equ         stackmagic,0xaffeaffe
.equ         stacksize, 1024


stacktop:    .int     stackmagic
stack:       .space   stacksize,0
stackbottom: .int     stackmagic

使用一些代码至少定期检查(例如,在定时器中断例程中,或者 - 如果可用 - 在您的调试器中)stackmagic 值是否仍然存在。