允许堆在短期范围内分配对象以确保内存碎片的自由

Rol*_*zin 4 c++ embedded heap stack memory-fragmentation

我们在嵌入式系统环境中使用C++,基本上不需要任何类型的动态内存分配(例如,参见嵌入式应用程序中的内存管理资源,原因我们没有这样做).我们仍然不想没有一些很好的基于C++的功能,如STL容器和std :: string.对于第一个,我们在初始化时保留特定的大小,不会让容器超出其容量.对于后者(std :: string),我对如何"安全地"使用它们持怀疑态度,因为它们有时会在堆上分配内存.

但是,我发现使用std :: string(通常是堆分配对象的其他方式)似乎很好:我将对象本身分配到堆栈上(在{}我说话的某个范围内)来自C++)并允许它们分配堆,前提是它们在超出范围时实际释放所有保留的内存.

我知道这种方法并不能保证内存碎片的自由,但我觉得如果手头的范围是短暂的,这实际上会导致在范围结束后连续的空闲内存.

我还怀疑当多个任务共享相同的堆但仍然是空闲内存时最终可能存在问题,只要手头的范围都是短暂的(例如不阻塞).或者,我可以接受只允许一个任务在堆上分配内存,而其他任务实际上不重要.

我建议的堆分配对象的用法是否有效?有人有另一种策略(部分)启用动态内存分配而不会有内存碎片的风险吗?

Mic*_*gan 5

我们过去在紧密的嵌入式系统上完成了各种C++风格的动态内存分配.你只需要遵循一些规则,并注意mxing短期和长期缓冲.首先,内存池是你的朋友 - 正如文章所说.

此外,对于C++喜欢在帮助配对和控制结构时所做的所有小(<64字节)分配,单位分配方案是必不可少的 - 不仅用于碎片控制,还用于性能.单元分配器预先分配许多相同大小的内存单元(比如64字节)并将它们放在一个空闲堆栈上.在分配内存时,将它们从空闲堆栈中弹出并返回它们.由于所有大小都相同,因此只有块大小的内部碎片.因为完成后你不必加入内存,所以分配和释放是O(1)时间.

其他一些规则:如果您需要进行长期的动态分配,请不要在此之前进行任何短期分配.首先分配大缓冲区,然后分配小缓冲区,以便内存不会分散.另一个系统是在堆的后面放置长期分配,在前面放置短期分配.我们也取得了成功.

您还可以使用多个堆(池)来隔离不同类型的分配.如果你有一些东西在代码的一个部分创建了一大堆短期分配,而另一个部分遵循不同的模式,给它们一个不同的堆.

如果仔细遵循,以上所有内容将阻止或限制碎片.另一种解决方案是使用可重定位的内存分配系统,其中低优先级线程可以重新排序内存以使其随时间保持连续.我已经看过这样做了几次 - 交易一点性能为0长期碎片.

alloca 也可以提供帮助,但是如果你没有遵循内存碎片预防方法,那么你也只会散布你的堆栈 - 而这往往是嵌入式土地中更有价值的资源,这可能不是一个好主意.