我该如何确定嵌入式系统中运行的C程序的当前堆栈和堆大小?同时,我该如何发现我的嵌入式系统允许的最大堆栈和堆大小?我考虑使用逐步增加分配内存大小并调用malloc()直到无法找到堆大小的方式,但我更关心堆栈的大小。我正在使用mbed NXP LPC1768,并且正在使用名为gcc4mbed的GitHub离线编译器。有更好的想法吗?非常感谢您的帮助!
要解决这个问题,请查看您的链接脚本,它将定义每个空间分配了多少。
对于堆栈大小的使用,请执行以下操作:
在启动时(在C main()之前)初始化内存时,将所有堆栈字节初始化为已知值,例如0xAA或0xCD。运行程序,在任何时候都可以停止并查看剩余的幻数值数量。如果没有看到任何幻数值,则已经溢出堆栈,可能会发生奇怪的事情。
在运行时,您还可以检查最后4个字节左右(可能是最后两个字),如果它们与您的幻数不匹配,则强制重置。这仅在系统在重置时表现良好时才有效,并且最好快速启动并且未执行“实时”或关键任务。
这是来自IAR的非常有用的白皮书。
static void* mainsp;
main
: int main(int argc, char**argv) {
int here;
mainsp = (void*) &here;
然后在一些叶子例程中,当调用栈足够深时,执行类似的操作
int local;
printf ("stack size = %ld\n",
(long) ((intptr_t) &local - (intptr_t) mainsp));
从应用程序的完整源代码中静态估计所需的堆栈大小通常是不可判定的(考虑递归、函数指针),在实践中也非常困难(即使在一个严格受限的应用程序类别上)。可以查看Couverture。您也可以考虑使用最新的GCC编译器自定义您的插件(也许在2021年中期使用Bismon;请给我发送电子邮件至basile.starynkevitch@cea.fr
),但这并不容易,并且会给出过度估计。
-Wstack-usage=
字节大小和/或-Wframe-larger-than=
字节大小警告选项来最近的GCC。/proc/self/maps
文件。请参阅proc(5)。您可以使用setrlimit(2)在Linux中的用户空间限制堆栈空间。使用多线程应用程序可能会更加困难。 阅读一些Pthread教程。
请注意,在简单情况下,GCC可能能够进行尾递归优化。 您可以使用gcc -Os -fverbose-asm -S foo.c
编译foo.c
并查看生成的foo.s
汇编代码。
如果您不关心可移植性,请考虑还使用GCC的扩展的asm
功能。
&sp
实际上应该是 &here
。 - ouahchar *stack_ptr asm ("sp");
来获取对当前堆栈指针的别名。 在像mbed这样的ARM Cortex-M3上,“sp”是堆栈指针的名称,但您需要更改其他架构以使用该方法。 如果您有许多本地变量,则这将非常有用。 - Kevin Vermeer