problem with delete[] aray

Hello,

I am working on a project where I need to delete my arrays in the loop in order to not run out of SRAM.

My problem :

I initialise my array before the setup
int* A = new int[300];

I fill it in the loop. It's an array of notes coming from a MIDI keyboard. I have to initalise the array before the loop because the function that fills this array (function called in the loop) have to be before the loop (that's how it's supposed to be in the MIDI library).

It looks like that :

  • initialisation of the array A of notes
  • function f called when I press a key. It fills the array A with the note and moves towards the next line.
  • loop. It calls function f each time a key is pressed.

I do a lot of stuffs in the loop an delete the array when it is not needed anymore : delete A;

The whole program works fine the first time.

Problem : When the loop restarts, the array of notes fill itself again (everything's fine) but the program stops when it's time to delete A again. (I moved the delete and yes, the program always stops at this precise time.)

Is there any way I can 'reinitialise' my table A at the beginning of the loop so that the delete can work at the end of the loop ?
Other hints about what's happening ?

Hope I was clear, please tell me if not.

Cheers,

Cedric

Where’s the code?
(Sorry be so brutal, but it’s about the third time today I’ve had to state the obvious)
I can’t really see why you would ever want to use new/delete in such a simple scenario.

If A is local to loop(), there is no need to allocate and deallocate the array. The compiler handles that.

ced13:
I do a lot of stuffs in the loop an delete the array when it is not needed anymore : delete A;

I think the correct syntax then would be:

delete(A);

The main page of code is 719 lines. I thought it would be nice to simplify the problem. If I cut everything I think is not related it would give :

#include <Arduino.h>
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

int longAcquisition=300;
byte* notes = new byte[longAcquisition];              

int i=0;

void MyNoteOn(byte channel, byte pitch, byte velocite) {        //Function called when a key is pressed
    notes[i]=pitch;          
    i=i+1;
  }

void setup() {
   Serial1.begin(31250); 
   MIDI.begin(1);  
   MIDI.setHandleNoteOn(MyNoteOn);         //MyNoteOn will be the function called when a key is pressed
}

void loop() {

     i=0;
     while(acquisition==HIGH){      //acquisition is a button
         MIDI.read();   //Function that watch MIDI inputs and calls MyNoteOn when a key is pressed
     }
     // end of acquisition

     sizeNotes=i;

     // Calculations with my array

     delete[] notes;

     //Calculations
}

notes is initialised before the loop because it is used by the function MyNoteOn that is defined before the loop.
I need to deallocate it cause otherwise my program runs out of memory before the end of the loop …
It is highly likely that I could have written it in another less SRAM-consuming way, but I don’t see how.

I am pretty sure the rest of the code is fine, cause everything works as exepected during the first passage into the loop.

During the first passage in the loop, the array seems to accept the delete, but in the second passage, I fill it again, the computation goes on until the delete line where it stops.

I use other arrays that I create in my loop and delete later and it works fine even in the second passage in the loop.

Thank you for your quick feedback

If you're just going to come around in loop and write up another array, then there's no need to delete it. Just write over it. Set i back to 0 and write over the array you already have.

Delta_G:
If you're just going to come around in loop and write up another array, then there's no need to delete it. Just write over it. Set i back to 0 and write over the array you already have.

If I do that, I run out of sram for the last part of my calculations. Even the first passage in the loop doesn't finish.

If I do that, I run out of sram for the last part of my calculations. Even the first passage in the loop doesn’t finish.

If you don’t have room for a static array, you don’t have room for a dynamic array. It is silly to think that you do.

Post your real code. Otherwise, you look like a doofus.

     while(acquisition==HIGH){      //acquisition is a button
         MIDI.read();   //Function that watch MIDI inputs and calls MyNoteOn when a key is pressed
     }

If acquisition IS HIGH, how is it going to change while the while loop is running?

ced13:
her arrays that I create in my loop and delete later and it works fine even in the second passage in the loop.

That sounds as if you are fragmenting the heap like a Swiss-style cheese, and at some point you have many, but small fragments of free RAM available, and none of them is big enough to assign a new array.

Do you have error checking in your sketch?
Error checking whether dynamical memory allocations are OK or fail at runtime?

int* A = new int[300];
if (A==NULL) ... // memory allocation failed

PaulS:
If you don't have room for a static array, you don't have room for a dynamic array. It is silly to think that you do.

It may be uninformed but not silly, please be friendly.
I have the space for the whole array, but then I creates other arrays based on this one, and do calculations on the notes. That's why I deallocate my first array, to get enough sram to do other calculations and manipulate other arrays. I am not an Arduino expert, maybe I didn't understand your sentence, tell me if I'm still wrong.

PaulS:
Post your real code. Otherwise, you look like a doofus.

I can't since it's more than 9000 caracters.

PaulS:

     while(acquisition==HIGH){      //acquisition is a button

MIDI.read();   //Function that watch MIDI inputs and calls MyNoteOn when a key is pressed
    }



If acquisition IS HIGH, how is it going to change while the while loop is running?

I was too lazy to introduce the declaration of the button and to add ' acquisition=digitalRead(bouton_acquisition);' but it's not the point, because this part works fine the first time it goes into the loop.

jurs:
That sounds as if you are fragmenting the heap like a Swiss-style cheese, and at some point you have many, but small fragments of free RAM available, and none of them is big enough to assign a new array.

Do you have error checking in your sketch?
Error checking whether dynamical memory allocations are OK or fail at runtime?

int* A = new int[300];

if (A==NULL) ... // memory allocation failed

No I don't do this, but I will. Is there a way to re-arrange memory to get bigger fragments ?
But in my case, the program stops when I try to delete an array. It looks like I have enough memory to complete a loop when I delete arrays after they become useless for my calculations.

Also, I don't understand how my array of notes can be filled again in the 2nd loop even if it has been deallocated in the first one and not reallocated. (code before the setup is only performed once, right ?)
It is like if it still exists and can be filled with new notes, but at the same time it can't be deallocated a second time.

Post complete code that demonstrates the problem please. If it is too long then attach it.

ced13:
No I don't do this, but I will. Is there a way to re-arrange memory to get bigger fragments ?

No, with AVR GCC you don't have anything like a "garbage collector", neither automatically nor manually, to compact a fragmented heap.

The only way to keep the heap unfragmented is: Do not use dynamically allocated/freed memory blocks.

Instead try to do something like that, if you need temporary array storage.

  • define a static array that is big enough to hold the biggest array you will need in your program
  • then reuse that big space each time you need a smaller array

I attached my code, the main page.

I record notes from a keyboard, I fill vectors with notes, times, velocity. Then I extract left hand, right hand, monophonic notes. I compute features (functions on other files) and make an association with ingredients with fuzzy rules (on other files). Then I realise the cocktail with pumps.
The code is a bit messy, it’s my first project on arduino. The main page deals with buttons, leds and the different tables of notes. Comment are in french as well. Not sure you will have the courage to go through this.

Thank you anyway

structure_acquisition.ino (21.8 KB)

Otherwise I could just reset the board at the end of the loop. From an exterior point of view, that's the same. Only problems, when the arduino is off, pumps commands are not controlled and it sucks my beverages out for a few milliseconds.. Could probably solve this on the hardware part but I don't want to go that way.

If you're worried about RAM usage, then why are you throwing RAM away on constant strings? Wouldn't that be a more obvious place to start trying to fix this?

Serial.print(" Rhum blanc : ");  // wastes 15 bytes of RAM storing the constant string
Serial.print(F(" Rhum blanc : "));  // uses 0 bytes of RAM to store the constant string

Simply cause I didn't know.
Thank you for the tip.

What Arduino is this?

int longAcquisition = 300;
unsigned long* tmpDebut = new unsigned long[longAcquisition]; // 0
int* duree = new int[longAcquisition];               // 1
byte* notes = new byte[longAcquisition];               // 2
byte* velocity = new byte[longAcquisition];           // 3

There goes 2400 bytes straight away.

You allocate that memory in global scope, and then:

        delete [] tmpDebut;
        delete [] duree;
        delete [] velocity;
        delete [] notes;

And then you never re-allocate it. So those pointers are only good once.

Plus, it is dangerous to call functions like "new" outside of a function.

Plus, why not make them a static array?

Eg.

int duree [longAcquisition];               // 1
byte notes [longAcquisition];               // 2
byte velocity [longAcquisition];           // 3

(And never delete them, of course).

  byte j = 0;
  while (j < 16) {
    pinMode(pompes[j], OUTPUT);
    j = j + 1;
  }

I suggest you read up on for loops.

for (byte j = 0; j < 16; j++)
      pinMode(pompes[j], OUTPUT);

It's the mega. Yep I know it consumes lot of memory, but I need those 300 notes. I understand that it's not good to allocate it globally and use it in the loop but I don't see other way to do this.
I used to have static arrays but when I ran out of memory, I decided to make them dynamic so that I can deallocate them. Otherwise I was limited to 50 notes, that's quite poor.

I should probably have doing that on raspberry, but I didn't know at that time.

Is there a way to re-allocate them in the beginning of the loop so that I can delete them more than once ?

Maybe with the space I freed from the serial.print I would have enough space to have static arrays but I'm not so sure.