Bonjour,
Un message pour Thierry et sa bibliothèque Accessories:
En utilisant la bibliothèque
Accessories, j'ai constaté une
fuite de mémoire. Cela se produit si un
Accessory a un
debounceDelay > 0. Car dans ce cas, un empilement des évènements reçu pendant le
debounceDelay a lieu ce qui réserve de la mémoire et cela est normal.
Le programme pour mettre en évidence le problème est très simple: un bouton poussoir qui active/désactive un relais.
Voici le programme.
#include "Commanders.h"
#include <Accessories.h>
#include <MemoryUsage.h>
const int buttonPin = 3; // broche du poussoir
const int relaisPin = 4; // broche du relais
ButtonsCommanderPush Bouton;
PortOnePin Port;
AccessoryLight Relais;
void ReceiveEvent(unsigned long inId, COMMANDERS_EVENT_TYPE inEventType, int inEventData)
{
Accessories::ReceiveEvent(inId, (ACCESSORIES_EVENT_TYPE)inEventType, inEventData);
}
void setup()
{
Serial.begin(115200); // console ARDUINO PC
Commanders::begin(ReceiveEvent);
Accessories::begin();
Bouton.begin(100, buttonPin);
Port.begin(relaisPin, DIGITAL_INVERTED);
Relais.begin(&Port, 100);
// Cas 1, Je fixe un debounce de 0s => tout ce passe bien
// Relais.SetDebounceDelay(0);
// Cas 2, Je fixe un debounce de 2s pour mettre en évidence le fait que la RAM libre diminue
Relais.SetDebounceDelay(2000);
PRINT_COMMANDERS()
PRINT_ACCESSORIES
}
void loop(void)
{
MEMORY_PRINT_FREERAM
Commanders::loop();
Accessories::loop();
}
Deux cas sont à considérer:
- Cas 1: je mets
Relais.SetDebounceDelay(0), soit pas de temps de
debounce et tout ce passe correctement:
la RAM libre est stable.- Cas 2: je mets
Relais.SetDebounceDelay(2000), soit un
debounce de 2 secondes (volontairement excessif pour mettre en évidence ce cas) pour actionner le relais.
Un premier appui sur le BP puis un deuxième avant 2s pour provoquer le debounce, et là, à chaque message "debounce : cant move !", un empilement a lieu (pour mémoriser l'évènement qui ne peut être exécuter tout de suite) réservant à chaque boucle de la RAM jusqu'à ce que le temps du
debounce soit écoulé.
Après analyse, les événements mémorisés sont bien "dépilés" et exécutés, mais la mémoire utilisée n'est pas libérée, ce qui à terme fait qu'un nouveau "
new" n'aura plus de mémoire pour "empiler" de nouveaux évènements qui seront alors perdus.
J'ai regardé dans le fichier
Accessories.cpp dans la méthode
Accessories::loop() où l'on "dépile" les évènements en attente, à priori c'est
Action *act = ActionsStack::Actions.GetActionToExecute();
if ( act != NULL )
Accessory::ExecuteEvent(act->Id, act->Event, act->Data);
J'ai testé un
delete à l'endroit suivant:
Action *act = ActionsStack::Actions.GetActionToExecute();
if ( act != NULL )
{
Accessory::ExecuteEvent(act->Id, act->Event, act->Data);
delete act; // libère la mémoire de l'évènement précédemment exécuté
}
La RAM libre est stable. Je ne sais pas si c'est l'endroit le plus approprié pour ce
delete, je ne connais pas les subtilités de Accessories !
En espérant contribuer à la consolidation des fondations de
Accessories !
Cyrille