4

如何确定嵌入式系统上正在运行的 C 程序的当前堆栈和堆大小?另外,我怎样才能发现我的嵌入式系统允许的最大堆栈和堆大小?我考虑过线性调用 malloc() 并增加大小,直到找不到堆大小,但是我对堆栈的大小更感兴趣。

我正在使用 mbed NXP LPC1768,并且正在使用在 GitHub 上开发的名为 gcc4mbed 的离线编译器。

有更好的想法吗?非常感谢所有帮助!

4

2 回答 2

10

为此,请查看您的链接器脚本,这将定义您为每个脚本分配了多少空间。

对于堆栈大小的使用,请执行以下操作:

在内存初始化期间启动时(在 C main() 之前),将所有堆栈字节初始化为已知值,例如 0xAA 或 0xCD。运行你的程序,在任何时候你都可以停下来看看你还剩下多少魔法值。如果你没有看到任何魔法值,那么你的堆栈溢出了,奇怪的事情可能会开始发生。

在运行时,您还可以检查最后 4 个字节左右(可能是最后两个字,这完全取决于您)。如果它们与您的魔法值不匹配,则强制重置。这仅在您的系统在重置时表现良好并且最好快速启动并且没有执行“实时”或关键任务时才有效。

这是IAR关于该主题的一份非常有用的白皮书。

于 2012-07-28T13:28:53.617 回答
7

在运行时测量当前堆栈大小的一种粗略方法是声明

 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

如果使用 GCC 编译,您可能会使用返回地址 bultins在运行时查询堆栈帧指针。在某些架构上,它不适用于某些优化标志。您还可以对最近的 GCC使用-Wstack-usage=字节大小和/或-Wframe-larger-than=字节大小 警告选项。

至于堆和堆栈空间如何分布,这取决于系统。/proc/self/maps您可能会在 Linux 上解析文件。请参阅proc(5)您可以使用setrlimit(2)在用户空间中限制 Linux 上的堆栈空间。

但是请注意赖斯定理

对于多线程应用程序,事情可能会更加困难。阅读一些Pthread 教程

请注意,在简单的情况下,GCC 可能能够进行尾调用优化。您可以编译您foo.cgcc -Os -fverbose-asm -S foo.c并查看生成的foo.s汇编代码。

如果您不关心可移植性,也可以考虑使用 GCC 的扩展asm功能

于 2012-07-28T13:03:47.817 回答