是否可以使用operator new来从堆以外的地方分配?

时间:2015-04-01 16:36:01

标签: c++ memory-management embedded

以下是我的应用程序的上下文:我正在使用一个使用来自不同设备的RAM的嵌入式系统。微控制器内部RAM(128kB)中的一部分是外部RAM(1MB)。这些存储器映射到微控制器的地址空间,但是在非连续区域中。

内部RAM用于系统堆栈,任务堆栈和堆。 外部RAM用于静态分配的数据(池,缓冲区和所有“static ...”内容)

我正在尝试实现一个简单的内存管理结构,并且作为其中的一部分能够创建一个分配器,它可以使用operator new的分配算法,但使用另一个内存源,而不是系统堆而是内存其他地区。你知道这是否可能吗?

使用的一个例子是保留100kB的外部RAM并创建一个分配器来管理它,然后将它交给需要这个内存的指定任务。

static const uint8_t* ramBase = reinterpret_cast<uint8_t*>(0x80000000);
static const uint32_t ramAreaSize = 0x19000; //100kB
BufferAllocator allocator(ramBase, ramAreaSize);

//...
//Assuming operator new is overloaded to use BufferAllocator
MyObject * obj = new (allocator) MyObject(some, parameter);
//...

问题是:如何(如果可能的话)我可以实现BufferAllocator以便使用operator new来管理原始内存区域吗?

void* BufferAllocator::allocate(uint32_t bytes)
{
    //I would like to write something like this
    //and so let the responsibility to manage this memory area to "new"
    //so I don't have to reimplement (or reuse) a different custom  
    // allocator
    return ::operator new(ramBase, ramAreaSize, bytes)
} 

2 个答案:

答案 0 :(得分:0)

我也面临同样的问题,我能找到的唯一解决方案是编写自己的mallocfree。我并不需要任何特别的东西,所以我只是在K&amp; R&#C> C编程语言中显示了我的代码之后(他们有一个简单的例子记录了)。

然后我创建了两个堆:一个用于内部存储器,一个用于外部存储器。我的堆栈是一个完全不同的内存块(STM32F4上的CCRAM),所以我不需要担心sbrk。但是,我必须根据数据大小和bss段知道内部SRAM堆的起始地址。这是由链接器脚本注入的extern符号确定的。

我有足够的关于我的堆的信息来了解它的当前大小,可用空间量以及是否有足够的连续内存来执行分配。如果内部SRAM不够,它会尝试外部SRAM。如果那里的内存不足,则与默认malloc内存不足有任何不同。

我正在使用GNU工具链,因此我可以使用--wrap选项覆盖C标准库的默认mallocfree,{{1} }和realloc(实际上callocmalloc_rfree_rrealloc_r,因为我使用的是newlib)。由于calloc_rnew最终致电delete和朋友,我能够让它发挥作用(至少是为了我的需要)。

我对这种方法并不十分自信,但在我的能力范围内,这是我能做的最好的事情。仔细考虑一下。

我很想知道一个更简单的解决方案。

答案 1 :(得分:0)

没有标准方法可以为operator newmalloc()提供内存区域。在类似POSIX的系统中,malloc()调用brk()sbrk()和可能mmap()来获取区域,因此您可以“捕获”这些调用并提供自己的实现,但是,这是不可移植的(mmap()的问题)。

根据您的工具链,您可能能够向您的malloc()和/或operator new“解释”它应该处理两个或更多不同的内存区域,在某些链接器脚本或某些此类内容中。但是没有保证。

除此之外,我能想到的唯一通用解决方案是在项目中使用不同的通用内存管理器(如jemalloc),并找到一种方法来配置它。