malloc(), realloc().. the dark side powerful it is

skyjumper:
I have not tried it yet, but its high on my priority list. I'll report back after I try it and run this test.

Okay I tried it... Who needs to sleep anyhow? I applied this to Arduino 1.0.

After following the instructions, everything seemed to work. The compiler and linker did their thing and AVRDude uploaded the resulting HEX file with no errors! So far so good. Then I tried to run a simple sketch, and discovered that the sketches can not talk back to my terminal. Hm... I tried again with the original 1.0 and ran the ASCII Table example, which worked fine. Back to the modified version, no joy. Maybe after some sleep things will be better...

Andy, thanks for confirming that! Your blog rocks, by the way!

Okay, the new tool chain works with my Uno board, just not with my 1284P board. The differences are primarily, the boot loader and of course the CPU.

More to come...

#define free myfree

I'm impressed, Nick. Less so with Arduino. This product is far too mature (old) to have that sort of thing still in it. Refusing to incorporate what appears to be a thoroughly worked out fix does not inspire much confidence for anything more than tinkering. :roll_eyes:

I'll have a closer look a getting a Tweeny.

 Serial.println ("String test ...");
 showmem();
 stest ();
 showmem ();

Is that your own util fn? I dont find that in /usr/share/arduino*

See reply #18 which I'll reproduce here:


Andy Brown wrote a library that debugs memory allocation in detail, by walking the free list.

Thanks for the link to Andys funcs I had not read the full three pages, but that does not seem to be the origin of showmem() . Though it provides the guts to get similar output.

memdebug.h :

extern size_t getMemoryUsed();
extern size_t getFreeMemory();
extern size_t getLargestAvailableMemoryBlock();
extern size_t getLargestBlockInFreeList();
extern int getNumberOfBlocksInFreeList();
extern size_t getFreeListSize();
extern size_t getLargestNonFreeListBlock();

I'd been looking for something like that yesterday. Cool.

thx

I see now I used Andy's stuff and just wrote my own showmem to output the results:

void showmem()
{
  char buffer[100];
 
  sprintf(buffer,"%04u %04u %04u : used/free/large",
      getMemoryUsed(),
      getFreeMemory(),
      getLargestAvailableMemoryBlock()
    );
 
  Serial.println(buffer);
}

Thanks , I guessed that was the case. However, I'm having trouble including Andy's code into my sketch.

I copied over his .c and .h files into the same directory as my sketch file , then added #include directive:

#define DEBUG 1
#include "memdebug.h"

however, when I try to reference the functions I get "not declared in this scope" errors.

If I deliberately mis-spell the file name I don't even get an error and verbose output does not show any -I for it.

Is this some Arduino voodoo stripping out the #include , or am I just too tired and missing the obvious?

The exact error message please? What isn't declared?

Try:

extern "C" 
  {
  #include "memdebug.h"
  }

One error masking another.

If I comment out the call to the memory functions the problem is that is not finding the include file

Fading_serial.cpp:11:22: error: memdebug.h: No such file or directory

I don't see why it did not report that initial error before but blocked on an later error that was a consequence of failing the include.

#include <SD.h>

/*
  sample ADC inputs 0-5 every 3s
  -255 marks end of data.
  monitor USB input for "d" command, then dump data to usb
  Fade led on/off during each data cycle
*/


#define DEBUG 
#include "memdebug.h"


int ledPin = 9;    // LED connected to digital pin 9

byte cells[] = {A0,A1,A2,A3,A4,A5};
int const maxcell = 5;
int const samples = 270; // 6x341=2kB
int const NaN=-1;
int current = 0;
int sample = 0;
byte data[samples][maxcell+1];


char const sDump[] = "# ADC data dump from Arduino";
char const sSampling[] = "# sampling A0..A5 from pin:";
char const sSample_num[] = "# sample num=";
char const sChar_read[] = "char read";

void setup()  { 
  // nothing happens in setup 
  Serial.begin(9600);
  Serial.print(sSampling);
  Serial.println(A0); 
  data [0][0] = NaN;
//  getFreeMemory();
//  showmem();
}

This would suggest that sketchbook directory (which is also the current directory on starting IDE) is not where the compilation is being run.

does arduino ''cd' somewhere else before calling avr-gcc ??

Yes it does. Did you make tabs in the IDE for those files? If not it won't copy them to the temporary place it does the compiling. More simply, make them a library. Just put memdebug.c and memdebug.h into a memdebug directory inside the libraries folder and restart the IDE.

Hmm, this seems like a typical result of trying to make things "simpler" my making them more obscure.
It's hard to get things in the right place if it's going to quietly move things elsewhere before compiling.

Thanks for the explanation.

I added tabs for the .h and .c but now it fails with "unterminated endif"

When I look at the tab with memdebug.c I can see why.

at line 89 onwards everything has become concatenated onto one !!

The result is that the terminating #endif // DEBUG is not at the beginning of a line and does not get parsed correctly.

Not only does it copy stuff elsewhere, it mangles the source before doing so.

Is there a 90 line limits to tabs ???

Hmm.

I have edited the code in the IDE tab to insert newlines at the appropriate places and at least it compiles now.

However, if I open the original .c file it has not changed ! Clearly what I am editing in the IDE is NOT the file that I selected. Labelling the tab with the file name is very misleading. On the evidence of what I'm seeing it clearly is now something else.

Is there a description of all this voodoo somewhere?

thanks again.

I think the tabs are kept in memory. I wouldn't edit them on disk while the sketch is open.

Thanks Nick. I now have this compiling at least. Now to test...

There seems to be a bug in "Add file" . I'll have to look into that and open another thread.

I did a copy paste from Andy's code on the web page and pasted into nano editor. I don't see much likelihood of it missing the line feeds on the latter half of that copy.

More likely a bug in IDE when it imports longer files.

Nick, I have added your replacement for free() to the arduino installation's wired.c and added the following to the top of stdlib.h

// nick's fix for heap allocation bugs
#define free good_free

Now by making a typo in either file I can get a compilation error, so I know I'm in the right files and that they are getting rebuilt when I compile a sketch.

However, if do not rename "myfree" to good_free it still compiles, indicating that this #define is not redirecting calls to free.

Am I missing a step to link this in?

Thx.

Well I tried adding Paul's malloc.c as suggested in his bug report.

It did not work since it gave an error about redefining malloc() . This was not surprising since there was no malloc.c where he suggested putting it so it was bound to be a double declaration. Maybe his suggestion was aimed at an earlier version.

Anyway, once I removed it again it must have force a rebuild of something since I now got the error I was expecting from the incorrect naming of the free() replacement in stdlib.h

Correcting both names to be good_free() now works and a test shows same memory before and after your stest() call.

0000 0820 0824 : used/free/large
0000 0820 0824 : used/free/large

It would be good to have full instructions on how to force the necessary rebuild for your replacement free() to take effect. It's something to do with restarting the IDE but that's not enough on its own, I'd done that several times already.

Thanks for providing the code.

I seem to recall that the newest IDE doesn't necessarily recompile all the library files. So that is probably what happened to you.

Just as an update,

Related issue 857: Google Code Archive - Long-term storage for Google Code Project Hosting. avr-libc 1.6.4 dynamic memory (malloc, free) bug, was marked solved today.

If I understand correctly, the fix is to include in the arduino core (Arduino/hardware/arduino/cores/arduino/) a new file named malloc.c with the code found at

or

which introduces: "malloc, free, realloc from avr-libc 1.7.0 with minor modifications, by Paul Stoffregen"

It did the trick for me, no more crashes so far from dealing with String operations.

Nick, fuh, Andy and the rest of you guys, thanks, you have saved me from a lot of trouble by bringing this issue up and contributing to it's solution!