2026/3/28 7:52:22
网站建设
项目流程
网站建设全屏,杭州网站建设技术支持,廊坊网站seo,展示系统 网站模板随着项目变得复杂#xff0c;有时候系统会莫名卡死#xff0c;原因之一很可能就是栈溢出了。而栈溢出不一定会立刻出问题#xff0c;所以不容易及时发现。那如何了解栈的使用情况呢#xff1f;下面就使用嵌入式操作系统和裸机系统分别介绍查看方法。嵌入式操作系统#xf…随着项目变得复杂有时候系统会莫名卡死原因之一很可能就是栈溢出了。而栈溢出不一定会立刻出问题所以不容易及时发现。那如何了解栈的使用情况呢下面就使用嵌入式操作系统和裸机系统分别介绍查看方法。嵌入式操作系统FreeRTOS这里以FreeRTOS系统为例它提供了获取栈使用量的函数和栈溢出时的回调函数直接调用和配置即可。这个函数会获取task运行过程中栈空间的最小剩余量这个值越小栈越接近溢出根据这个值调整栈空间的大小一般预留20%左右的余量。FreeRTOS还提供了栈溢出钩子函数发生栈溢出时调用它只能做一些善后工作无法恢复系统想要调用钩子函数还需要在FreeRTOSConfig.h中定义下面的宏这个宏的值可以是1、2、3较新的版本才会有31检测栈指针是否越界2检测栈区最后的20字节是否被覆盖3检测ISR的栈。实测1会直接触发系统的HardFault并调用HardFault_Handler回调函数2会调用钩子函数推荐设置成23不会调用钩子函数。建议在HardFault回调中也输出信息裸机系统对于裸机系统可以自己定义函数检测。用特定的字符填充栈区后面通过这些字符判断栈的使用情况栈的信息在ld链接文件中定义ld中的是设置变量的地址而不是变量的值所以引用的时候需要加。栈指针指向的是栈区已使用的末端地址而不是未使用的首地址所以要先减再赋值。stack_init函数可以在main中最开始调用不过会破坏进入main的调用栈数据由于嵌入式系统进入main后一般不会返回所以不影响程序的运行。如果不想破坏可以把这个函数放到startup文件中的Reset_Handler函数内SystemInit之前这样完全不会影响后边程序运行的栈区数据。之后从栈区开始逐个比较栈区数据和填充数据如果不一样说明这个地址的数据被入栈操作覆盖这样便可以得出栈的最大使用量。调用时尽量放到程序执行的末尾让所有函数都执行一次这样才能获得较准确的栈最大使用量。读取sp寄存器可以获得当前栈指针位置获取当前栈使用情况标准库的printf有多层函数调用尤其打印浮点数时有log打印和没log打印栈的使用情况是不同的所以有时候栈溢出程序异常时去掉printf就能正常运行。如果必须输出log除了调大栈空间也可以使用其它轻量级的printf库比如FreeRTOS的printf-stdarg.c这些库可以一定程度优化栈的使用不过一般不支持浮点。