Memory leak with BigNumber and toString()

Hi,

I'm using BigNumber library on my project which is running on a Mega2560. Very fast, I encounter a freeze. I've find out that I've got a memory leak. I've pointed out my problem in a very short sketch which reproduce the problem :

#include "BigNumber.h"
#include "MemoryFree.h"

void setup ()
{
  Serial.begin(115200);
  BigNumber::begin(10);
}

void loop () {
  BigNumber bigNumber("1");
  String bigNumberChar = bigNumber.toString();
  Serial.print("freeMemory()=");
  Serial.println(freeMemory());
}

Which outputs :

freeMemory()=7834
freeMemory()=7830
freeMemory()=7826
freeMemory()=7822
freeMemory()=7818
freeMemory()=7814
freeMemory()=7810
[...]
freeMemory()=194
freeMemory()=190
freeMemory()=186
freeMemory()=182
freeMemory()=178
freeMemory()=174
freeMemory()=170
freeMemory()=166
freeMemory()=162
freeMemory()=158
freeMemory()=154
freeMemory()=150
freeMemory()=146

I've solved my problem by replacing this String by a char* and a free().

#include "BigNumber.h"
#include "MemoryFree.h"

void setup ()
{
  Serial.begin(115200);
  BigNumber::begin(10);
}

void loop () {
  BigNumber bigNumber("1");
  char * bigNumberChar = bigNumber.toString();
  Serial.print("freeMemory()=");
  Serial.println(freeMemory());
  free (bigNumberChar);
}

But, few things annoys me :

  • Why this String cause a memory leak ?
  • I've used the String syntax in another part of my main projet and it works like a charm
  • I'd prefer to use String so as to easily manipulate them later

What do you think about this ?

The String class has long been a source of memory leaks and the problem is very well known. It is there only because somebody, at some point, thought that a char array was too difficult for a beginner to understand, but it really isn't. So, stay clear of this String thing, because everything you can do with it you can do without it. Once you have figured out how char arrays work, it's actually easier to use them instead of String, IMO.

Anything that uses dynamic memory allocation, String objects included, can lead to memory leaks. Strings are especially bad because it's so easy to do things that invoke the copy constructor which means you end up making multiple intermediate strings in RAM that you weren't aware of.

On an Arduino without much RAM, Strings can quickly lead to trouble.

That said, your example results are surprising - how do you have so little free memory with such a short piece of code?

That said, your example results are surprising - how do you have so little free memory with such a short piece of code?

I've edited my results. It starts higher.

BigNumber.h says:
char * toString () const; // returns number as string, MUST FREE IT after use!

Change:
String bigNumberChar = bigNumber.toString();
to:

  char * cp = bigNumber.toString();
  String bigNumberChar = cp;`
  free(cp);
3 Likes

The BigNumber.toString() method returns a pointer to a character (array), not a String object.

It dynamically allocates memory using malloc() but never frees it (as it can't because you would loose the result). Your solution is perfect.

This has nothing to do with the String class.

// Edit
I see that I was far to slow, @johnwasser beat me to it :wink:

1 Like