- 静态存储区域的大小在执行期间保持不变,但动态栈会随着激活记录的推入和弹出而增长和缩小。
- 在静态栈中,存储需求在执行前已知,但在动态栈中,栈帧的大小和结构在编译时已知,但实际内容和分配时间直到运行时才知道。
还有什么其他的差异,并且有人可以帮我提供一段代码片段吗? 谢谢。
还有什么其他的差异,并且有人可以帮我提供一段代码片段吗? 谢谢。
我能够提供一些见解,因为我目前正在开发一种使用静态栈的系统。
由于您提到了堆栈帧,您必须知道堆栈用于在进入更深层次的子程序时跟踪上下文。仅明确提及这一点是因为它与下一段相关。
通常,堆栈和堆被视为动态的,这意味着它们可以扩展其大小 - 通常使用类似于malloc()
等的内存管理来完成。这里展示了经典的图示(左面板)。正如您在中间面板中看到的那样,堆栈以井然有序的方式增长和缩小,因为内存只能在底部分配或释放。另一方面,堆可以在内部任何地方看到内存被分配/释放。当两个区域相遇时会发生冲突 - 这将导致一个大问题,因为无法调用更多的子例程。此外,很难预测这种情况何时会发生。
如果您想避免这种问题(例如在安全关键应用中),您可以选择禁止在堆栈+堆中使用动态内存。当您有信心您的程序永远不会超过特定深度的子例程调用时(例如没有递归,或递归被限制),使用静态堆栈是一个好的选择。使用静态堆栈也简化了实现,这是您在裸机应用程序中可能会关注的。
以下代码是如何在启动代码中实现静态堆栈的小例子:
//*****************************************************************************
//
// Reserve space for the system stack.
//
//*****************************************************************************
__attribute__ ((section(".stack")))
static uint32_t g_pui32Stack[1024];
section
属性允许您使用链接脚本在内存中定位堆栈:
ENTRY(Reset_Handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x0000C000, LENGTH = 960K
SRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 384K
}
SECTIONS
{
.text :
{
/* This is where executable code gets stored */
} > FLASH
/* User stack section initialized by startup code. */
.stack (NOLOAD):
{
. = ALIGN(8);
*(.stack)
*(.stack*)
. = ALIGN(8);
} > SRAM
.data :
{
/* This is where global/static initialized variables are stored */
} > SRAM AT>FLASH
.bss :
{
/* This is where global/static 0-filled variables are stored */
} > SRAM
.heap (COPY):
{
/* This is where dynamically allocated storage could be used */
} > SRAM
}
您可以看到,在这种情况下,堆栈不会位于堆的旁边...静态堆栈可以放在任何地方,因为假设您永远不会超出其边界。