Free malloc'ed memory issue [RESOLVED]

Hi all,

I have a question regarding memory allocation.
I know that using heap on Arduino is a discouraged practice, but I have to do because I must instantiate objects from a own-created library.

But here I’ll start with a simpler example. I want to reserve memory for a single integer and then release it.
I implemented the new and delete C++ operators within the CPlusPlusFixes library, and a method to show how much RAM is available within the FreeMemory library instead.

The strange thing is that when using new/delete the memory is correctly de-allocated, while when using malloc/free it is not.

Output with new/delete:

Free available memory (bytes): 7499
Free available memory (bytes): 7495
Free available memory (bytes): 7499

Output with malloc/free:

Free available memory (bytes): 7499
Free available memory (bytes): 7495
Free available memory (bytes): 7495

Here’s my example code:

#include <FreeMemory.h>
#include <CPlusPlusFixes.h>

void setup()
{
  Serial.begin(57600);
  
  int *int1 = 0, *int2 = 0;

  printFreeMemory();
  int1 = new int;
  printFreeMemory();
  delete int1;
  int1 = 0;
  printFreeMemory();

//  int1 = (int *) malloc(sizeof(int));
//  printFreeMemory();
//  free(int1);
//  int1 = 0;
//  printFreeMemory();
}

void loop() { }

void printFreeMemory (void)
{
  Serial.print("Free available memory (bytes): ");
  Serial.println(getFreeMemory());
}

Can anyone point me to the right direction to solve this problem? Thanks in advance.

I post here the code for the CPlusPlusFixes library. It contains the definition of the new and delete operators plus the memory fix founded here: http://arduino.cc/forum/index.php/topic,46948.0.html

CPlusPlusFixes.h

#ifndef _CPP_FIXES_H_
#define _CPP_FIXES_H_

#include <WProgram.h>

struct __freelist
{
  size_t sz;
  struct __freelist *nx;
};

extern struct __freelist *__flp;
extern uint8_t* __brkval;

void * operator new (size_t num);
void * operator new[] (size_t num);
void operator delete (void *ptr);
void operator delete[] (void *ptr);
void fix28135_malloc_bug (void);

#endif

CPlusPlusFixes.h

#include "CPlusPlusFixes.h"

void * operator new (size_t num)
{
  return malloc(num);
}

void * operator new[] (size_t num)
{
  return malloc(num);
}

void operator delete (void *ptr)
{
  free(ptr);
  fix28135_malloc_bug();
}

void operator delete[] (void *ptr)
{
  free(ptr);
  fix28135_malloc_bug();
}

void fix28135_malloc_bug (void)
{
  for (__freelist *fp = __flp, *lfp = 0; fp; fp = fp->nx) {
    
    if (((uint8_t *) fp + fp->sz + 2) == __brkval) {
      
      __brkval = (uint8_t *) fp;
      
      if (lfp) { lfp->nx = 0; }
      else { __flp = 0; }
      break;
    }
    lfp = fp;
  }
}

Here it is the code of the FreeMemory library (based on the example from the Arduino Playground).

FreeMemory.h

/*
 * Count the remaining free bytes in RAM.
 */

#ifndef FREE_MEMORY_H
#define FREE_MEMORY_H

#ifdef __cplusplus
extern "C" {
#endif

int getFreeMemory (void);
int checkMem (void);

#ifdef  __cplusplus
}
#endif  // ifdef __cplusplus

#endif  // ifndef FREE_MEMORY_H

FreeMemory.cpp

#include "WProgram.h"  
#include "FreeMemory.h"

//extern unsigned int __data_start;
//extern unsigned int __data_end;
//extern unsigned int __bss_start;
//extern unsigned int __heap_start;

// top of the static variable memory
extern unsigned int __bss_end;
// top of the heap (0 if malloc() is not used)
extern void *__brkval;

int getFreeMemory (void)
{
  int free_memory;

  if ((int) __brkval == 0) {
    free_memory = ((int) &free_memory) - ((int) &__bss_end);
  }
  else {  // malloc is used
    free_memory = ((int) &free_memory) - ((int) __brkval);
  }

  return free_memory;
}

int checkMem (void)
{
  byte *heapptr = 0;
  byte *stackptr = 0;

  // retrieve the value of the heap pointer
  stackptr = (byte *) malloc(4);
  heapptr = stackptr;
  free(stackptr);
  // retrieve the value of the stack pointer
  stackptr = (byte *) SP;
  
  return (stackptr - heapptr);
}

When you use new and delete, fix28135_malloc_bug() gets called after the delete calls free(). When you use malloc() and free() directly, it does not. So I guess you are seeing the bug that fix28135_malloc_bug() is intended to fix.

Using new or malloc() is OK in setup() code, but I advise against using delete or free() anywhere. If you really want to allocate and free objects, consider maintaining your own freelist of same-size objects instead.

You're right dc42,

and I feel really stupid for the question, instead. :blush:

Using new or malloc() is OK in setup() code, but I advise against using delete or free() anywhere.

Why malloc() is ok in setup() code only? What will happen if I use it in loop() code?

If you really want to allocate and free objects, consider maintaining your own freelist of same-size objects instead.

Can you point me to an example, please?

ramo102: Why malloc() is ok in setup() code only? What will happen if I use it in loop() code?

I've written about the problems of dynamic memory allocation in embedded systems at http://critical.eschertech.com/2010/07/30/dynamic-memory-allocation-in-critical-embedded-systems/. That article is written in relation to critical embedded systems, but the same principles apply to any embedded system based on C/C++.

The main danger is that your free memory will fragment and a malloc or new call will fail when there is sufficient total free memory but it is divided into chunks that are all too small to satisfy the current request. The system runs until this happens, then crashes. In PC based programs running Windows or Linux, the problem is typically masked by virtual memory, however I have known applications run out of address space (typically 2Gb max for 32-bit programs) due to memory fragmentation.

If your malloc/free or new/delete calls are always for exactly the same size object, fragmentation should not occur and you may get away with it.

Thanks dc42,

I already know about the memory fragmentation problem on embedded systems.

My malloc/free are almost always for the same size objects, except a few special cases (5% of the total, more or less) where a different sized object is created.

Thanks again for your suggestions and for the useful link.

dc42:

ramo102: Why malloc() is ok in setup() code only? What will happen if I use it in loop() code?

If your malloc/free or new/delete calls are always for exactly the same size object, fragmentation should not occur and you may get away with it.

I googled for an example of a custom freelist implementation, but I cannot find it. Do you have some links? Thanks in advance.

Unfortunately I don't have any examples of custom freelist implementation to hand. The principle is:

  • include a link field in your object so that you can chain free objects together (normally you will re-use one of the existing fields)
  • declare a freelist root pointer for each class as a static member of the class
  • when you want to allocate a new object of the class, look in the freelist first, if it is not empty then take an object off that and use it. Only allocate a new object from the heap if the freelist is not empty.
  • when you want to free an object, just put it on the freelist.

You can overload placement new and delete operators for the class in order to make this transparent, so that this all happens under the covers when you use new and delete as normal.

The disadvantage is that memory in the freelist for one class cannot be used for allocating objects of a different class. The advantage is that fragmentation is avoided.