我应该使堆栈段大还是堆段大? [英] Should I make stack segment large or heap segment large?

查看:195
本文介绍了我应该使堆栈段大还是堆段大?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为具有非常有限内存的微处理器编程设计,我必须在不同的功能中使用大量的内存。我不能有一个大的堆栈段,堆段,数据段,我必须选择哪个做大,哪个做小。我共有约32KB,

I'm programming a design for a microprocessor with very limited memory and I must use "a lot" of memory in different functions. I can't have a large stack segment, heap segment, data segment, I must choose which to make big and which to make small. I have about 32KB total,

我使用约20KB的文本段,其余的为12KB。我需要一个4KB的缓冲区来传递到不同的功能(SPI Flash扇区大小)。哪里应该初始化那个大缓冲区?

I use about 20KB for the text segment, that gives me 12KB for the rest. And I need a buffer of 4KB to pass to different functions (SPI Flash sector size). Where should initialize that large buffer?

所以我的选择是:

1)如果我将缓冲区函数的开始,堆栈将需要做大

1) If I declare the buffer at the beginning of the function, the stack would need to be made large

spiflash_read(...)
{
  u8 buffer[4096]; // allocated on stack 
  syscall_read_spi(buffer,...)
}

2)动态分配,堆将需要做大

2) Allocate dynamically, the heap will need to be made large

spiflash_read(...)
{
  u8 *buffer = (u8*) malloc(4096); // allocated in heap
  syscall_read_spi(buffer,...)
}

3)静态分配,在SPI库之外不能使用的巨大的下行端口。

3) Allocate statically, huge down side it can't be used outside the "SPI Library".

static u8 buffer[4096]; // allocated in data section.

spiflash_read(...)
{
  syscall_read_spi(buffer,...)
}

我的问题是实现这种设计的最佳方法是什么?有人可以解释推理吗?

My question is which is the best way to implement this design? Can someone please explain the reasoning?

推荐答案

静态分配总是运行时安全,因为如果你的内存不足,链接器将在buid时间告诉你,而不是在运行时崩溃的代码。但是,除非在执行期间永久性地要求存储器,否则这可能是浪费的,因为分配的内存不能重用于多个目的,除非您以这种方式显式地编码。

Static allocation is always run-time safe since if you have run out of memory, your linker will tell you at buid time rather than the code crashing at run-time. However, unless the memory is required permanently during execution, it can be wasteful, since the allocated memory cannot be re-used for multiple purposes unless you explicitly code it that way.

动态内存分配是运行时检查 - 如果你用完了,malloc()返回一个空指针。然而,您需要测试返回值,并根据需要释放内存。动态内存块通常为4或8字节对齐,并承载堆管理数据开销,使其对于非常小的分配而言效率低下。同样频繁地分配和分配广泛变化的块大小可能会导致堆碎片和浪费的内存 - 这对于永远在线的应用来说可能是灾难性的。如果你永远不会释放内存,它将永远被分配,并且你知道你需要多少,那么你可能会更好地使用静态分配。如果您有库源,您可以修改malloc以立即停止内存分配失败,以避免检查每个分配。如果分配大小通常为几个常用大小,则固定块分配器而不是标准的malloc()可能更为可取。这将是更确定的,您可以实施使用情况监控,以帮助优化每个大小的块大小和数量。

Dynamic memory allocation is run-time checkable - if you run out of heap, malloc() returns a null pointer. It is however beholden upon you to test the return value, and to release memory as necessary. Dynamic memory blocks are typically 4 or 8 byte aligned and carry a heap management data overhead that make them inefficient for very small allocations. Also frequent allocation and deallocation of widely varying block sizes can lead to heap fragmentation and wasted memory - it can be disastrous for "always-on" applications. If you never intend to release the memory, and it will always be allocated, and you know apriori how much you need, then you may be better off with static allocation. If you have the library source, you could modify malloc to immediatly halt on memory allocation failure to avoid having to check every allocation. If the allocations sizes are typically of a few common sizes, a fixed-block allocator rather then the standard malloc() might be preferable. It would be more deterministic, and you could implement usage monitoring to aid optimisation of block sizes and numbers of each size.

堆栈分配是最有效的,因为它自动获取,根据需要返回内存。但是它还具有很少或没有运行时检查支持。通常,当堆栈溢出发生时,代码将无法确定地失败 - 并不一定在任何地方附近根本原因。一些连接器可以生成堆栈分析输出,通过调用树计算最坏情况下的堆栈使用情况;你应该使用这个,如果你有这个设施,但请记住,如果你有一个多线程系统,将有多个堆栈,你需要检查最坏的情况下,每个入口点。此外,lonker不会分析中断堆栈使用情况,您的系统可能会有一个单独的中断堆栈或共享系统堆栈。

Stack allocation is the most efficient as it automatically gets and returns memory as necessary. However it also has little or no run-time checking support. Typically when a stack overflow occurs, the code will fail non-deterministically - and not necessarily anywhere near the root cause. Some linkers can generate stack analysis output that will calculate worst-case stack usage through the call tree; you should use this if you have that facility, but remember that if you have a multithreaded system, there will be multiple stacks, and you need ot check the worst case for the entry point to each. Also the lonker will not analyse interrupt stack usage, and your system may have a separate interrupt stack, or share the system stack.

我将解决这个问题的方式当然不是在堆栈上放置大数组或对象,但按照以下过程:

The way I would tackle this is certainly not to place large arrays or objects on the stack but follow the following process:


  1. 使用链接器堆栈分析计算最坏情况堆栈如果需要,允许使用ISR的附加堆栈。分配这么多堆栈。

  1. Use the linker stack analysis to calculate worst case stack usage, allow additional stack for ISRs if necessary. Allocate that much stack.

静态分配执行期间所需的所有对象。

Allocate all objects required for the duration of execution statically.

如果您的库包含堆诊断功能,可能会在您的代码中使用它们来监视堆的使用情况,以检查你的耗尽程度。

If your library includes heap diagnostic functions, you might use them within your code to monitor heap usage to check how close you are to exhaustion.

链接器分析最坏的情况可能会比你更大在实践中看到 - 我从未被执行的最坏情况路径。您可以使用特定字节(例如0xEE)或模式预填充堆栈,然后经过广泛的测试和操作,检查高潮标记并优化堆栈。谨慎使用此技术;您的测试可能无法涵盖所有​​可预见的情况。

The linker analysis "worst-case" is likley to be larger that waht you see in practice - the worst case paths my never be executed. You could pre-fill teh stack with a specific byte (say 0xEE) or pattern, then after extensive testing and operation, check for the "high-tide" mark and optimise the stack that way. Use this technique with caution; your testing may not cover all forseeable circumstances.

这篇关于我应该使堆栈段大还是堆段大?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆