Freeing resources used by a third party library

Hello,

I am building a system that reads once a day new parameters from a web server, using HTTP, and SIM800 library by Olivier Staquet.

The library uses a destructor, with this code:

/**
 * Destructor; cleanup the memory allocated by the driver
 */
SIM800L::~SIM800L() {
  free(internalBuffer);
  free(recvBuffer);
}

After reading the web server parameters, I want to make sure all resources generated by the "new" created object are destroyed, and memory released.

How to make sure this happens ?

My calling code (that is only the part that reads from server):

#include <SIM800L.h>

/********************************************************************************
 * Example of HTTPS GET with SoftwareSerial and Arduino-SIM800L-driver          *
 *                                                                              *
 * Author: Olivier Staquet                                                      *
 * Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
 ********************************************************************************
 
 *******************************************************************************/
 /* Stripped down version GET removed
Using library SIM800L in folder: D:\AsusCloud\Electronica\Arduino\Development\libraries\SIM800L (legacy)
Using library SoftwareSerial at version 1.0 in folder: C:\Users\horac\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\SoftwareSerial 
"C:\\Users\\horac\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\horac\\AppData\\Local\\Temp\\arduino\\sketches\\B24C07207DABA7577980D9D52EF9430B/HTTPS_GET_SoftSerial_testHbb_1_StrippedDown.ino.elf"
Sketch uses 12378 bytes (38%) of program storage space. Maximum is 32256 bytes.
Global variables use 530 bytes (25%) of dynamic memory, leaving 1518 bytes for local variables. Maximum is 2048 bytes.
*/

//HBB DELETE SEEMS TO DO NOTHING
// att remove delete and pointer study
#include <SoftwareSerial.h>

#define SIM800_RX_PIN 8
#define SIM800_TX_PIN 9
#define SIM800_RST_PIN 6

//const char APN[] = "datos.personal.com";
const char APN[] = "em";
const char URL[] = "http://nutritronix.com/selectV201W.php";
const char CONTENT_TYPE[] = "application/x-www-form-urlencoded";
const char PAYLOAD[] = "api_key=tPmAT5Ab3j7F9&device#=BC94";

SIM800L *sim800l;

void setup() {  
  Serial.begin(9600);   // Initialize Serial Monitor for debugging
  Serial.println(F("Start setup POST testHbb_1_strippedDown-01.ino")); //  while(!Serial); hbb what for ? 
                  //A-> just to wait in some AvrS serial init before executing
  SoftwareSerial* serial = new SoftwareSerial(SIM800_RX_PIN, SIM800_TX_PIN);// Initialize a SoftwareSerial
  serial->begin(9600);
  delay(1000);
  // Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
  sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512);
  int hbb;
  hbb = (unsigned int)sim800l;
  Serial.print("sim800l (before): ");
  Serial.println(hbb, HEX);
  //delete sim800l;
  hbb = (unsigned int)sim800l;
  Serial.print("sim800l (after): ");
  Serial.println(hbb, HEX);
  
  // Equivalent line with the debug enabled on the Serial
  // sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
  setupModule(); // Setup module for GPRS communication
}
 
void loop() {
 // Establish GPRS connectivity (5 trials)
  bool connected = false;
  for(uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    connected = sim800l->connectGPRS();
  }
  // Check if connected, if not reset the module and setup the config again
  if(connected) {
    Serial.print(F("GPRS connected with IP "));
    Serial.println(sim800l->getIP());
    Serial.println(sim800l->getDES());
  } else {
    Serial.println(F("GPRS not connected !"));
    Serial.println(F("Reset the module."));
    sim800l->reset();
    setupModule();
    return;
  }

  Serial.println(F("Start HTTP POST..."));

// Do HTTP POST communication with 10s for the timeout (read and write)
  uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, PAYLOAD, 10000, 10000);
   if(rc == 200) {
    // Success, output the data received on the serial
    Serial.print(F("HTTP POST successful ("));
    Serial.print(sim800l->getDataSizeReceived());
    Serial.println(F(" bytes)"));
    Serial.print(F("Received : "));
    Serial.println(sim800l->getDataReceived());
  } else {
    // Failed...
    Serial.print(F("HTTP POST error "));
    Serial.println(rc);
  }
  delay(1000);

  // Close GPRS connectivity (5 trials)
  bool disconnected = sim800l->disconnectGPRS();
  for(uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    disconnected = sim800l->disconnectGPRS();
  }
  
  if(disconnected) {
    Serial.println(F("GPRS disconnected !"));
  } else {
    Serial.println(F("GPRS still connected !"));
  }

  // Go into low power mode
  bool lowPowerMode = sim800l->setPowerMode(MINIMUM);
  if(lowPowerMode) {
    Serial.println(F("Module in low power mode"));
    sim800l='0';
  } else {
    Serial.println(F("Failed to switch module to low power mode"));
  }
  
}

void setupModule() {
  // Wait until the module is ready to accept AT commands
  //HBB
    Serial.print(F("Reseting SIM800L..."));
    sim800l->reset();
    delay(10000);
    Serial.print(F("End Reset SIM800L..."));


  while(!sim800l->isReady()) {
    Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
    delay(1000);
  }
  Serial.println(F("Setup Complete!"));

  // Wait for the GSM signal
  uint8_t signal = sim800l->getSignal();
  while(signal <= 0) {
    delay(1000);
    signal = sim800l->getSignal();
  }
  Serial.print(F("Signal OK (strenght: "));
  Serial.print(signal);
  Serial.println(F(")"));
  delay(1000);

  // Wait for operator network registration (national or roaming network)
  NetworkRegistration network = sim800l->getRegistrationStatus();
  while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
    delay(1000);
    network = sim800l->getRegistrationStatus();
  }
  Serial.println(F("Network registration OK"));
  delay(1000);

  // Setup APN for GPRS configuration
  bool success = sim800l->setupGPRS(APN);
  while(!success) {
    success = sim800l->setupGPRS(APN);
    delay(5000);
  }
  Serial.println(F("GPRS config OK"));
}

Thanks a lot !
Regards,
Horacio
delete sim800l;

Thanks for your time !

Delta_G,

I will try to work it in a special function, seems a good way.

Memory intensive: Yes, I do have a lot of stuff and need to be very cautious with memory, if not, it will not fit, and I will need more hard resources than a 328.

fgvalvo:

I tried

delete sim800l;

using that delete at the end of loop, to force in the next cycle the use of an undefined object, get a crash and be sure the SIM800L class object is destroyed.

But I am surprised, the loop continued to get good results from the server.
I am confused in the use of delete in this context.

When I test delete with VS Code with a sample Class it works as expected.

Thanks again, and have a very nice week end !
Horacio

consequent usage of F-Makro might save some SRAM:

  Serial.print("sim800l (before): ");
  Serial.println(hbb, HEX);
  //delete sim800l;
  hbb = (unsigned int)sim800l;
  Serial.print("sim800l (after): ");

To be expected :slight_smile:

I'm not sure if the pointer to a deleted object is set to NULL. But you can force that yourself.

delete sim800l;
sim800l = nullptr;

And before you want to use it again, you check if sim800l points to an object or not

if(sim800l == nullptr)
{
  sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512);
}
if(sim800l == nullptr)
{
  // inform user
  Serial.println(F("Creating sim object failed"));
  // hang forever
  for(;;);
}

There are two if statements; the second one checks if the creating succeeded.

Instead of hanging forever, you can test every time that you want to do something with the object if it's a valid object.

E.g.

  bool connected = false;
  if(sim800l != nullptr)
  {
    for(uint8_t i = 0; i < 5 && !connected; i++)
    {
      delay(1000);
      connected = sim800l->connectGPRS();
    }
}

Note:
Creating the sim800l object in setup() is not needed if you want to free the resources and later recreate them again in loop().

Hello,

All answers are of great help, thanks so much!
I will try to get ATMega 4808, in 28 pin fmt, with SRAM going from 2k to 6k.
This Avr seems to be an easy upgrade. I don't know if this avr is available in Buenos Aires.
Will see tomorrow. If available, I can even keep my PCB layout, with little redesign.
And test all the soft possibilities you mention,
Thanks again!
Horacio

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.