嵌入式C程序中未使用的间隙';s任务堆栈

嵌入式C程序中未使用的间隙';s任务堆栈,c,stack,rtos,C,Stack,Rtos,在运行带有多个任务的RTOS的嵌入式C开发中,每个任务都有自己的堆栈,为什么堆栈在使用的部分之间会有未使用的间隙 堆栈在启动时使用已知模式填充,以确定最坏情况下的堆栈使用情况。当使用IDE内存查看器在运行时查看堆栈内容时,可以在正常堆栈数据之间看到已知模式的间隙 例如: Stack top ----------------- unused area ----------- used area 2 ----------- unused area ----------- used area 1 --

在运行带有多个任务的RTOS的嵌入式C开发中,每个任务都有自己的堆栈,为什么堆栈在使用的部分之间会有未使用的间隙

堆栈在启动时使用已知模式填充,以确定最坏情况下的堆栈使用情况。当使用IDE内存查看器在运行时查看堆栈内容时,可以在正常堆栈数据之间看到已知模式的间隙

例如:

Stack top
-----------------
unused area
-----------
used area 2
-----------
unused area
-----------
used area 1
-----------------
Stack bottom
为什么正常的堆栈使用会留下一个间隙而不是连续的数据

如有任何建议,欢迎提出, 谢谢

更新

为了回答这些问题,在总堆栈大小为0x400字节的单个堆栈上可以看到96字节的单个间隙

谢谢你的评论,这里有一些很好的建议。在这种情况下,我可以根据间隙的大小和单个引用规则对齐。未初始化的阵列可能是原因,因为所有其他RAM最初都使用与堆栈相同的模式填充


我的另一个(令人担忧的)想法是堆栈指针损坏,但这似乎不太可能,因为软件运行时不会出现问题。

签名模式是确定堆栈使用情况的一种方法,但不是一种完美的机制-如果从未向变量写入任何内容,则不会修改该模式

“未使用”是一个误导性术语;而不是修改是一个更好的描述

这通常发生在缓冲区可能未充分利用的情况下。例如,如果你说:

char string_buff[128] ;

sprintf( string_buf, "%s", "hello" ) ;
只会写入6个字符的
string\u buff
,并显示为122字节的“未使用”间隙

如果对代码进行了这样的修改:

char string_buff[128] = {0} ;

sprintf( string_buf, "%s", "hello" ) ;

整个缓冲区将以初始化整个缓冲区为代价显示为已使用。

签名模式是确定堆栈使用情况的一种方法,但不是一种完美的机制-如果从未向变量写入任何内容,则不会修改模式

“未使用”是一个误导性术语;而不是修改是一个更好的描述

这通常发生在缓冲区可能未充分利用的情况下。例如,如果你说:

char string_buff[128] ;

sprintf( string_buf, "%s", "hello" ) ;
只会写入6个字符的
string\u buff
,并显示为122字节的“未使用”间隙

如果对代码进行了这样的修改:

char string_buff[128] = {0} ;

sprintf( string_buf, "%s", "hello" ) ;

整个缓冲区将显示为已使用,但需要对整个缓冲区进行初始化。

我不能完全确定我是否理解您的意思。
堆栈之间的间隙可以来自链接器在每个堆栈的“顶部”(即堆栈增加方向)插入一个安全阈值,以防止任务堆栈完全被任务例程耗尽并且发生中断的情况——在非托管情况下,中断,事实上,CPU的优先级协议允许的所有可能的中断,可能会在每个任务上增加最大堆栈使用率。在托管情况下(大多数RTO管理中断处理,或者至少可以配置为这样做),中断条目的至少一小部分将临时驻留在任务堆栈上,直到操作系统矢量移动到系统堆栈,该系统堆栈将处理当前和所有更高优先级的ISR的堆叠。因此,在托管中断方案中,每个堆栈顶部都需要有一个安全裕度。

我不能完全确定我是否理解您的意思。
堆栈之间的间隙可以来自链接器在每个堆栈的“顶部”(即堆栈增加方向)插入一个安全阈值,以防止任务堆栈完全被任务例程耗尽并且发生中断的情况——在非托管情况下,中断,事实上,CPU的优先级协议允许的所有可能的中断,可能会在每个任务上增加最大堆栈使用率。在托管情况下(大多数RTO管理中断处理,或者至少可以配置为这样做),中断条目的至少一小部分将临时驻留在任务堆栈上,直到操作系统矢量移动到系统堆栈,该系统堆栈将处理当前和所有更高优先级的ISR的堆叠。因此,在托管中断方案中,每个堆栈顶部都需要有安全裕度。

如何检查堆栈?它们有多大?它们都一样大吗?你能看到一种模式吗?“间隙”的大小加上下一个使用区域是否一致?它们是否总是以似乎表示模式的地址开始或结束?您是否查看了生成的代码,以确定编译器是否在函数调用帧之间添加了一些空间?您是否更愿意关心是否所有堆栈都已满,并且您编写的每个任务都存在堆栈溢出问题?要求堆栈帧具有一些对齐并不罕见(例如,AMD64 SystemV ABI上的16个字节可容纳SSE类型)。这些间隙有多大?如果您的任何函数声明一个未初始化的数组,并且可能只使用其中的一部分,这将显示为您的原始模式?您如何检查堆栈?它们有多大?它们的大小是否相同?是否有您可以看到的模式?是否有“间隙”的大小加上下一个使用区域的一致性?它们总是以似乎指示模式的地址开始或结束吗?您是否查看了生成的代码,以确定编译器是否在函数调用帧之间添加了一些空间?您是否更愿意关心是否所有堆栈都已满,并且您编写的每个任务都遭受堆栈溢出?这是一个问题要求堆栈帧具有某种对齐(例如AMD64 SystemV ABI上的16字节以适应SSE类型)并不罕见。这些间隙有多大?如果您的任何函数声明未初始化的数组,并且可能只使用其中的一部分,这将显示为您的原始模式?