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

时间:2015-03-28 21:16:40

标签: arduino microcontroller avr avr-gcc atmel

我一直在寻找几天没有运气。

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

如果使用它们是不可避免的,我怎么能不时地对堆进行碎片整理以确保下一个malloc()调用会找到要分配的连续内存?

2 个答案:

答案 0 :(得分:4)

创建一个固定大小的内存块池。当您需要任何数量的内存时,从池中分配一个块并使用您需要的部分。完成后,将块返回池中。池永远不会碎片,因为块总是相同的大小。如果有任何块可用,那么它们总是合适的大小。有时候你只需要几个字节,而且你会觉得你因为整个组合而浪费了。但是你会记得你正在避免记忆碎片,你会感觉更好。

如果您的分配大小差别很大,那么一个固定大小的内存池可能真的太浪费了。然后,您可以为小型,中型和大型块创建两个或三个固定大小的内存池。但请确保将块返回到从中获取的池中。

使用队列或链接列表来组织池中的块。分配时,会从队列/列表中删除这些块。当他们被释放时,他们会返回队列/列表。

答案 1 :(得分:1)

正如@kkrambo所提到的,使用队列或链表来跟踪分配的内存块。我已经包含了一个专门针对Arduino的例子,它没有我所有想要的花里胡哨。 我选择只保留指向队列中的内存块的指针,而不是块本身(这似乎是kkrambo所说的,虽然我不知道他/她是否意味着我在上面说的话。 )

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);
}