如何使用 C++ 为 ARM Cortex 确定适当的堆栈和堆大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5278904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:48:28  来源:igfitidea点击:

How can I determine appropriate stack and heap sizes for ARM Cortex, using C++

c++embeddedarmcortex-m3

提问by rmaVT

The cortex M3 processor startup file allows you to specify the amount of RAM dedicated to the stack and the heap. For a c++ code base, is there a general rule of thumb or perhaps some more explicit way to determine the values for the stack and heap sizes? For example, would you count the number and size of unique objects, or maybe use the compiled code size?

cortex M3 处理器启动文件允许您指定专用于堆栈和堆的 RAM 量。对于 C++ 代码库,是否有一般的经验法则或一些更明确的方法来确定堆栈和堆大小的值?例如,您会计算唯一对象的数量和大小,还是使用编译后的代码大小?

回答by Clifford

The cortex M3 processor startup file allows you to specify the amount of RAM dedicated to the stack and the heap.

cortex M3 处理器启动文件允许您指定专用于堆栈和堆的 RAM 量。

That is not a feature of the Cortex-M3, but rather the start-up code provided by your development toolchain. It is the way the Keil ARM-MDK default start-up files for M3 work. It is slightly unusual; more commonly you would specify a stack size, and any remaining memory after stack and static memory allocation by the linker becomes the heap; this is arguably better since you do not end up with a pool of unusable memory. You could modify that and use an alternative scheme, but you'd need to know what you are doing.

这不是 Cortex-M3 的功能,而是您的开发工具链提供的启动代码。它是 M3 的 Keil ARM-MDK 默认启动文件的工作方式。这有点不寻常;更常见的是,您会指定堆栈大小,链接器分配堆栈和静态内存后的任何剩余内存都将成为堆;这可以说是更好,因为您最终不会得到无法使用的内存池。您可以修改它并使用替代方案,但您需要知道自己在做什么。

If you areusing Keil ARM-MDK, the linker options --info=stack and --callgraph add information to the map file that aids stack requirement analysis. These and other techniques are described here.

如果你正在使用的Keil ARM-MDK,连接选项--info =堆栈和--callgraph信息添加到地图文件,艾滋病堆栈需求分析。此处介绍这些和其他技术。

If you are using an RTOS or multi-tasking kernel, each task will have its own stack. The OS may provide stack analysis tools, Keil's RTX kernel viewer shows current stack usage but not peak stack usage (so is mostly useless, and it only works correctly for tasks with default stack lengths).

如果您使用的是 RTOS 或多任务内核,则每个任务都有自己的堆栈。操作系统可能提供堆栈分析工具,Keil 的 RTX 内核查看器显示当前堆栈使用情况而不是峰值堆栈使用情况(因此几乎没有用,它仅适用于具有默认堆栈长度的任务)。

If you have to implement stack checking tools yourself, the normal method is to fill the stack with a known value, and starting from the high address, inspect the value until you find the first value that is not the fill byte, this will give the likley high tide mark of the stack. You can implement code to do this, or you can manually fill the memory from the debugger, and then monitor stack usage in a debugger memory window.

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

Heap requirement will depend on the run-time behaviour of your code; you'll have to analyse that yourself however in ARM/Keil Realview, the MemManage Exception handler will be called when C++'s newthrows an exception; I am not sure if malloc()does that or simply returns NULL. You can place a breakpoint in the exception handler or modify the handler to emit an error message to detect heap exhaustion during testing. There is also a a __heapstats()function that can be used to output heap information. It has a somewhat cumbersome interface, I wrapped it thus:

堆需求将取决于代码的运行时行为;您必须自己分析,但是在 ARM/Keil Realview 中,当 C++new抛出异常时,将调用 MemManage 异常处理程序;我不确定是否malloc()这样做或只是返回NULL。您可以在异常处理程序中放置断点或修改处理程序以发出错误消息以在测试期间检测堆耗尽。还有一个__heapstats()函数可以用来输出堆信息。它有一个有点麻烦的界面,我这样包装它:

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

回答by semaj

The compiled code size will not help as the code does not run in the stack nor the heap. Cortex-M3 devices are typically implemented on microcontrollers with built in Flash and a relatively small amount of RAM. In this configuration, the code will typically run from Flash.

编译后的代码大小无济于事,因为代码既不在堆栈中也不在堆中运行。Cortex-M3 设备通常在具有内置闪存和相对少量 RAM 的微控制器上实现。在此配置中,代码通常从 Flash 运行。

The heap is used for dynamic memory allocation. Counting the number of unique objects will give you a rough estimate but you also have to account for any other elements that use dynamic memory allocation (using the newkeyword in C++). Generally, dynamic memory allocation is avoided in embedded systems for the precise reason that heap size is hard to manage.

堆用于动态内存分配。计算唯一对象的数量会给您一个粗略的估计,但您还必须考虑使用动态内存分配的任何其他元素(new在 C++ 中使用关键字)。通常,由于堆大小难以管理的确切原因,在嵌入式系统中避免动态内存分配。

The stack will be used for variable passing, local variables, and context saving during exception handling routines. It is generally hard to get a good idea of stack usage unless you're code allocates a large block of local memory or a large objects. One technique that may help is to allocate all of the available RAM you have for the stack. Fill the stack with a known pattern (0x00 or 0xff are not the best choices since these values occur frequently), run the system for a while then examine the stack to see how much was used. Admittedly, this not a very precise nor scientific approach but still helpful in many cases.

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

回答by Mark Lakata

The latest version of the IAR Compiler has a feature that will determine what stack size you need, based on a static analysis of your code (assuming you don't have any recursion).

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

The general approach, if you don't have an exact number, is to make as big as you can, and then when you start running out of memory, start trimming the stack down until your program crashes due to a stack over flow. I wish that was a joke, but that is the way it is usually done.

如果您没有确切的数字,一般的方法是尽可能大,然后当您开始耗尽内存时,开始削减堆栈,直到您的程序因堆栈溢出而崩溃。我希望那是个玩笑,但这是通常的做法。

回答by charles

Reducing until it crashes is a quick ad-hoc way. You can also fill the stack with a known value, say, 0xCCCC, and then monitor maximum stack usage by scanning for the 0xCCCC. It's imperfect, but much better than looking for a crash.

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

The rationale being, reducing stack size does not guarantee that stack overflow will munch something "visible".

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