0

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."); 
   }
3
  • 1
    _MiPrueba / _GsmSerial etc. are reserved identifiers. Don't use reserved identifiers. Commented Sep 4, 2024 at 14:27
  • 1
    @TedLyngmo: I had absolutely no idea about this... in fact, I though the convention for naming member variables was to prefix them with underscore. I stand corrected, thank you very much. UPDATE - if I got it right, underscore followed by lowercase is ok, right? Commented Sep 4, 2024 at 15:13
  • 1
    Yes, an identifier starting with underscore followed by a lowercase letter is ok if it's not in the global namespace, where that's reserved too. Commented Sep 4, 2024 at 15:29

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

thanks, that makes sense... but then, what would be the correct way to pass the pointer to Prueba() from Sim800Cls.init()? (I have tried to just call Prueba.init() passing it the pointer to the softserial, but it also throws an exception)
@patsy2k Why isn't PruebaCls p; a member variable instead of a local variable if you need it for as long as the instance of Sim800Cls lives? Replace PruebaCls *_MiPrueba; with PruebaCls _MiPrueba; and skip the local p (except, don't use the reserved identifier _MiPrueba).
@TedLyngmo: the downvote came after it was closed as a dupe. I see this as a sign that I should have voted to close instead of answering. But, you know ... since 25k I don't really care about rep any more.
Yeah, it could be could be connected to that, but I hope not. Your answer doesn't become "unhelpful" just because there are similar Q&As around.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.