Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.


Sujets - lapive

Pages: [1]
1
Bibliothèques / Bibliothèque Accessories
« le: mai 21, 2018, 06:11:46 pm »
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

Pages: [1]