两种检测方式在检测原理上存在一些差别,检测方式1是检测运行过程中的任务栈指针,检测方式2则是检测初始化后的数据在运行过程中是否被修改。2 E+ N) x8 X3 D7 c8 e
如果任务堆栈溢出检测函数检测到发生了堆栈溢出,则会调用对应的钩子函数(钩子函数需用户手动创建),用户可以在钩子函数中执行想要的操作例如打印发生错误的任务名等。3 S7 O! X" O5 T! p7 u, r. M* S
内核在什么时候执行任务堆栈溢出检测:在FreeRTOS源码 tasks.c 文件中可以查到taskCHECK_FOR_STACK_OVERFLOW在 void vTaskSwitchContext( void )函数中被调用,也就是在任务上下文切换的时候做检测。从这点可以看出软件检测栈溢出的方式具有一定的滞后性,需要在任务发生上下文切换时才会进行,任务堆栈溢出时并不能马上检测到问题。" L7 B) D2 c' b1 r- y* e) z 任务堆栈溢出检测存在的局限性:如上文所述,只有在发生任务上下文切换时才会执行任务堆栈溢出检测,发生如下错误情形时则无法检测到了: & L+ z* h0 v9 N& o# d. @• 任务执行的过程中出现过栈溢出,但任务切换前栈指针又恢复到了正常水平。' m5 B7 k: y2 p* n( M9 V" p
• 任务栈末尾的 16 个字节没有用到,即不会被修改,但是任务栈已经溢出了 % M* K+ s4 v* n( j, U8 M" C• 任务栈溢出后,把系统中的重要数据修改了导致系统直接进入Hardfault# R+ }0 [" a8 R' `6 n/ u
FreeRTOS提供的堆栈溢出检测会引入任务上下文切换的开销,因此仅推荐在应用开发或者测试阶段使用。虽然存在一定的局限性,但大多常见情况下这些检测机制依然是非常实用的功能,可以帮助用户减少代码中的错误并提高应用程序代码的质量。 0 b. i4 p0 f& |3 H6 N6 S% l. o5 w* Z* R" }8 R& y. v
9 A- K+ m& m. ^) A; v