Implementing New and Delete C++ Functionality for Arduino

I want to log a small amount of GPS data to the Arduino's memory. I know I can just create a large array and stack it with data, but that's got a serious drawback. The length of arrays is fixed at compile time. If I need to store more or less data in the future I have to modify, recompile and upload a new program to my Duemilanove.

What I need is dynamic memory allocation.

In the land of C and C++ code there exists a function called malloc. I've never used it, but I've read about it. I understand it allocates a block of memory and returns a void pointer to that location. The more I read about malloc the less I feel confident to use it. I've found you can cast a void pointer to a pointer of another type, but this can cause serious issues. I'm cool with pointers, but what I'm really hankering for is the good old New and Delete that I used in Software Engineering. These return pointers to objects and I know what to do with them. So why don't I just use New and Delete? I would, but they don't work.

Using New...

Widget *thing = new Widget();

... earns you the compiler error: "undefined reference to operator new"

It's interesting, the Arduino development environment colours the word new as if it's a recognised keyword. It's as if it's almost working. A little time surfing The Goog turns up a few pointers in the forum (post 1, post 2), the second of which links off to a great article on AVR Freaks. If the author can be believed, it's a simple case of building a new file called cppfix.h, pasting in his code and including it in sketches. Well, it works. And guess what, it implements malloc() to do it. So I have used malloc() to provide dynamic memory, even if indirectly.

The only amendment I made was to add #include <stdlib.h> inside the cppfix.h file. My complete cppfix.h looks like this:

#ifndef cppfix
#define cppfix

#include <stdlib.h>

__extension__ typedef int __guard __attribute__((mode (__DI__)));

void * operator new(size_t size);
void operator delete(void * ptr);

int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};

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

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

#endif

I created a bogus string library called CMString.h and instantiated it in my main sketch using the new keyword.

#include "cppfix.h"
#include "CMString.h"

CMString *thing = new CMString(15);

void setup()
{
Serial.begin(9600);
}

void loop()
{
Serial.println(thing->junk());
Serial.println("hello world");
delay(1000);
}

It compiled and ran, as I'd hoped it would. I'm now free to use the small library of C++ classes I've developed for Uni assignments. I should be able to use linked lists, queues, deques, trees and from there develop any kind of dynamic storage. This is potentially very useful stuff even in the Lilliputian land of Arduino. But I'm sure this boundless access to memory will sooner or later cause me problems - there's not a lot of it go around! I'll post more later.

That is all.

Comments

  1. Thank you, just what I needed!

    Note however that:

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

    will cause problems if ptr is null. This is safer:

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

    ReplyDelete
  2. Hello,

    Not that I know much of it, but I had to modify your cpp file to avoid compilers errors 'multiple definitions':
    #ifndef cppfix
    #define cppfix

    #include

    __extension__ typedef int __guard __attribute__((mode (__DI__)));

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


    // int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
    // void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
    // void __cxa_guard_abort (__guard *) {};


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

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

    #endif


    Thanks for the solution!
    Regards,
    Lode

    ReplyDelete
  3. Is it still necessary with the actual Arduino IDE (V1.0.4) ?

    ReplyDelete

Post a Comment