我正在STM32微控制器上创建应用程序。我正在使用一些库堆栈。在那个堆栈之上,我正在使用我的应用程序。我有两个问题:
如何在运行时检测和处理堆栈溢出。因为我不知道库正在使用多少内存。
如果我从头开始编写代码,如何在运行时检测和处理堆栈溢出。我读了一些我们必须为每个声明保留一些计数的地方。这是正确的方法还是找到它的任何标准方式。
答案 0 :(得分:2)
如果您的软件不是很小,我会首先尝试在您的笔记本电脑或台式机或平板电脑上调试大部分软件(可能运行Linux,因为它有很好的工具和非常标准的兼容编译器,类似于您的交叉编译器使用)。然后,您可以从valgrind或GCC等-Wall -Wextra -g -fsanitize=address
等编译选项等工具中获益。
您可以在main
函数的开头存储堆栈顶部的近似值(例如,在extern int* start_top_of_stack;
函数的开头附近执行int i=0; start_top_of_stack= &i;
然后main
。然后可以在几个函数中使用一些本地int j=0;
,并在开始时检查&j - start_top_of_stack
是不是太大。
但有no silver bullet。我只是在暗示一个技巧。
如果您的应用程序对于接受昂贵的开发工作至关重要,那么您可以使用一些formal method& source static program analysis工具(例如Frama-C,或使用MELT制作您自己的工具)。如果您使用最近的GCC进行交叉编译,则可能需要使用-Wstack-usage=
一些长度和/或-fstack-usage
来检查每个调用框架是否也是如此大,或手动计算所需的堆栈深度。
答案 1 :(得分:2)
如果您仅限于自己的设备并且没有“高级”工具,那么至少可以尝试“旧方法”。简单的堆栈防护可能有所帮助。代码中的某处(取决于您使用的工具),必须有堆栈区域的定义。类似于:
.equ stacksize, 1024
stack: .space stacksize,0
(gnu作为语法,你的可能会有所不同)
使用您设备的启动代码将堆栈寄存器初始化为stack
区域的顶部地址。
然后,一个堆栈守卫只会在堆栈顶部和底部添加一个“幻数”:
.equ stackmagic,0xaffeaffe
.equ stacksize, 1024
stacktop: .int stackmagic
stack: .space stacksize,0
stackbottom: .int stackmagic
如果stackmagic
值仍然存在,则至少会定期检查某些代码(例如,在计时器中断例程中或 - 如果可用 - 在调试器中)。