2011-03-11 54 views
12

皮质M3处理器启动文件允许用户指定的RAM专用于栈和堆的量。对于一个C++代码库,是否有一个通用的经验法则或者一些更明确的方式来确定堆栈和堆大小的值?例如,你会计算唯一对象的数量和大小,还是使用编译的代码大小?如何确定用于ARM皮质适当堆和栈大小,用C++

+0

这是比特定CPU架构更特定的编译器和运行时库。但最重要的是,这是确定内存使用情况的代码。使用MMU或数据断点捕捉堆栈溢出。 – 2011-03-12 00:10:24

+0

可能的重复[如何确定最大堆栈使用?](http://stackoverflow.com/questions/389219/how-to-determine-maximum-stack-usage) – 2011-03-12 10:53:03

+0

@本:Cortex-M3没有MMU,但它具有数据访问硬件断点支持,这可能有助于在测试期间提供帮助,但不能用于部署。 – Clifford 2011-03-12 21:54:30

回答

14

皮质M3处理器启动文件 允许指定的 RAM专用于堆叠中的量和 堆。

这不是在Cortex-M3的功能,而是由你的开发工具链提供的启动代码。这是M3的Keil ARM-MDK默认启动文件的工作方式。它有点不寻常;更常见的是你会指定一个堆栈的大小,堆栈和链接器分配的静态内存之后的剩余内存将成为堆;这可以说是更好,因为你不会结束一堆无法使用的记忆。你可以修改它并使用另一种方案,但你需要知道你在做什么。

如果您使用Keil ARM-MDK的,链接器选项--info = stack和--callgraph将信息添加到帮助堆栈需求分析的映射文件中。这些和其他技术被描述为here

如果您使用的是RTOS或者多任务处理内核,每个任务都会有它自己的堆栈。操作系统可能提供堆栈分析工具,Keil的RTX内核查看器显示当前堆栈使用情况,但不显示峰值堆栈使用情况(所以大多数情况下是无用的,并且只能用于默认堆栈长度的任务)。

如果您必须自己实现堆栈检查工具,常规方法是用已知值填充堆栈,并从高地址开始检查该值,直到找到第一个不是填充字节的值,这将给出堆叠的高潮标记。您可以实现代码来执行此操作,也可以手动从调试器中填充内存,然后在调试器内存窗口中监视堆栈使用情况。

堆需求将依赖于你的代码的运行时行为;你必须自己分析一下,但是在ARM/Keil Realview中,当C++的new引发异常时,将调用MemManage异常处理程序;我不知道如果malloc()这样做或简单地返回NULL。您可以在异常处理程序中放置断点,或修改处理程序以发出错误消息来检测测试期间的堆耗尽情况。还有一个__heapstats()函数可用于输出堆信息。它有一个有些繁琐的界面,我把它包这样的:

void heapinfo() 
{ 
typedef int (*__heapprt)(void *, char const *, ...); 
    __heapstats((__heapprt)std::fprintf, stdout) ; 
} 
3

编译后的代码大小将不利于为代码在栈也不是堆运行。 Cortex-M3器件通常在具有内置闪存和相对较少的RAM的微控制器上实现。在此配置中,代码通常将从Flash运行。

堆用于动态存储器分配。计算唯一对象的数量将会给你一个粗略的估计,但你也必须考虑使用动态内存分配(使用在C new关键字++)的任何其他元素。一般来说,嵌入式系统中避免动态内存分配的原因是堆大小难以管理。

堆栈将用于变量传递,局部变量和上下文中的异常处理例程节约。除非你是代码分配一大块本地内存或一个大对象,否则一般很难理解堆栈的使用情况。一种可能有用的技术是分配堆栈中的所有可用RAM。用已知模式填充堆栈(0x00或0xff不是最佳选择,因为这些值经常发生),运行系统一段时间,然后检查堆栈以查看使用了多少。诚然,这不是一个非常精确或科学的方法,但在许多情况下仍然有用。

1

IAR编译器的最新版本具有一项功能,可根据代码的静态分析(假设您没有任何递归)来确定需要的堆栈大小。

如果你没有确切的数字,一般的做法是尽可能大,然后当你开始用尽内存时,开始修剪堆栈直到你的程序崩溃,因为堆栈过流。我希望这是一个笑话,但这是通常的做法。

+0

事实上,这确实是大多数堆叠尺寸确定的方式,这对我们的行业来说是尴尬的! – odinthenerd 2015-05-12 11:25:34

0

减少到崩溃是一种快速临时方式。您也可以使用已知的值填充堆栈,例如0xCCCC,然后通过扫描0xCCCC来监视最大堆栈使用情况。 这是不完美的,但比寻找崩溃要好得多。

原理是,减少堆栈大小并不能保证堆栈溢出会产生“可见”的东西。