AVR/Arduino微控制器中有处理堆内存碎片的方法吗?

5

我已经搜索了几天,但没有找到答案。

堆内存碎片化是使用malloc()和free()在微控制器/Arduino中的结果。

如果无法避免使用它们,如何定期进行碎片整理以确保下一个malloc()调用将找到连续的内存来分配?


1
你可以修改malloc函数,使其返回一个指向内存块的句柄,然后编写一个函数,每次需要访问该内存块时将句柄转换为实际指针。这样,你就可以自己编写周期性重排内存并更新句柄表的碎片整理程序了。 - Jon
有趣,您有示例代码或可以指向该方向吗? - Islam Mustafa
2个回答

7
创建一个固定大小的内存块池。当你需要任何量的内存时,从池中分配一个块并使用所需部分。使用完后将块返回到池中。由于块始终是相同大小的,所以池永远不会出现碎片化。如果有任何块可用,则它们始终是正确大小的。有时您只需要几个字节,一瞬间您可能会认为占用整个块是浪费的。但是然后您会想起正在避免内存碎片,并且会感觉更好。
如果您的分配大小差异很大,则一个固定大小的内存池可能真的太浪费了。然后,您可以创建两个或三个固定大小的内存池,用于小型、中型和大型块。但务必将块返回到同一池中。
使用队列或链表来组织池中的块。当分配块时,块将从队列/列表中移除。当释放块时,它们将被返回到队列/列表中。

但如果必须使用malloc(),是否有任何方法可以对内存进行碎片整理? - Islam Mustafa
重置设备并重新初始化堆将对内存进行碎片整理。当malloc()失败、定期执行或在您的应用程序处于方便的状态时,可以进行重置操作。 - kkrambo
但这与碎片整理内存不同,后者将丢弃所有已分配的数据。 - Islam Mustafa

3

正如@kkrambo所提到的,使用队列或链表来跟踪分配的内存块。我已经提供了一个针对Arduino的示例,该示例没有我想要的所有功能。

我选择仅在队列中保留指向内存块的指针,而不是块本身(尽管我不知道他/她是否意味着我上面所说的内容)。

const int MAX_POOL_SIZE = 4;
const int MAX_DATA_SIZE = 128;

// Memory pool for data
QueueArray <uint8_t*> dataPool;

void initDataPool () {
  uint8_t * ptr;
  for (int i = 0; i < MAX_POOL_SIZE; i++) {
    ptr = (uint8_t*) malloc(MAX_DATA_SIZE);     // Allocate MAX_DATA_SIZE buffer
    dataPool.push(ptr);                         // Push buffer pointer to queue
  }
}

// Allocate message data buffer from data pool
// If data pool still has buffer space available, and requested
// buffer size is suitable, return pointer to avalable buffer
static void* allocateDataBuff (size_t buffSize) {
  if (!dataPool.isEmpty()) {
    if (buffSize < MAX_DATA_SIZE) return dataPool.pop();
    else {
      if (debugMsg) Serial.println("allocateDataBuff: Requested Buffer Size is too large");
      return NULL;
    }
  } // if message pool still has buffer space available
  else {
    if (debugMsg) Serial.println("allocateDataBuff: Memory pool is full, no buffers available at this time");  
  }
}
void setup() {
    initDataPool();
}
void loop() {
    // ........
    uint8_t* dataPtr = (uint8_t*) allocateDataBuff(100);
    // ....assign message to *dataPtr
    // ........
    deallocateDataBuff(dataPtr);
}

你没有提到 deallocateDataBuff() 函数... - Mohammad Kholghi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接