Search code examples
c++pointersarduino-esp32software-serial

esp32 c++ pointer to object is lost?


I dont understand why this is not working... will try to explain the best I can:

in main I need an object of class Sim800Cls. Sim800Cls on the other hand, needs an object of class Prueba. both Sim800Cls and Prueba need to use a software serial object, so both contains a private var that is a pointer to a softserial object.

So in main, I create a softserial object and a Sim800cls object. Then call Sim800Cls init() method passing it a pointer to the softserial. in Sim800Cls.init(), it assigns the pointer to its private var, then calls init() method of Prueba, passing it that same pointer. And in Prueba.init(), it just assigns the pointer to its own private variable.

in Sim800Cls.init(), just after calling init() of Prueba, I call a method of Prueba that uses the soft serial to check if it works. And it does. But outside of that init(), it breaks. It seems as if Prueba looses the pointer to the softserial or something like that... (the exception is thrown in sendCommand() method, at the line _GsmSerial->write(command.c_str());)

What is going on here? what am I doing wrong?

Main:

#include "Sim800Cls.h"
SoftwareSerial GsmSoftSerial;
Sim800Cls GsmSim800;     
   void setup() {
      ...
      GsmSoftSerial.begin(GSM_SOFT_SERIAL_BAUDS, SWSERIAL_8N1, GSM_SOFT_SERIAL_RX_PIN, GSM_SOFT_SERIAL_TX_PIN, false);
      while (!GsmSoftSerial) { ; }  // wait for serial port to connect.
      
      GsmSim800.init(&GsmSoftSerial);    //-> this runs ok
      GsmSim800.method1()                //-> this throws exception
      ...
   }

Sim800Cls.h:

   class Sim800Cls {
      private:
      protected:
         SoftwareSerial *_GsmSerial;
         PruebaCls *_MiPrueba;
   ...

Sim800Cls.cpp:

   void Sim800Cls::init(SoftwareSerial *GsmSoftSerial) {
      _GsmSerial = GsmSoftSerial;
      
      PruebaCls p;
      _MiPrueba = &p;
      _MiPrueba->init(GsmSoftSerial);
      delay(200);
      
      method1();    //-> this works
   }

   void Sim800Cls::method1() {
      _MiPrueba->test1();
   }

Prueba.h:

   class Prueba {
      private:
      protected:
         SoftwareSerial *_GsmSerial;
   ...

Prueba.cpp:

   void PruebaCls::init(SoftwareSerial *GsmSoftSerial) {
      _GsmSerial = GsmSoftSerial;
   }

   bool PruebaCls::test1() {
      std::string command, resp;
      command = "AT\r";
      sendCommand(command);
      resp = leeSerial();
      return true;
   }

   void PruebaCls::sendCommand(std::string &command) {
      Serial.print("[PruebaCls] in sendCommand() - sending command: "); Serial.println(command.c_str());
      _GsmSerial->write(command.c_str());    
      delay(50);
      Serial.println("[PruebaCls] in sendCommand() - command sent."); 
   }

Solution

  • PruebaCls p; is a local variable, let's assme it's on the stack (typically it will be, if it's not in a register).

    _MiPrueba = &p; refers to that variable.

    As long as execution is inside Sim800Cls::init(SoftwareSerial *GsmSoftSerial), that will work, since the variable is still in scope.

    Once you left the init() method, the local variable is destructed and the stack is overwritten by something else, thus calling method1() results in undefined behavior.