Class object does not populate well outside scope

Hi Everyone,

To begin with, Arduino-STL library is excellent for people who are sandwiched between C++ and Arduino. :slight_smile: Nevermind, I have started to use this library and it works with most of my cases except the situation my single global class object is giving different address at two places.

Consider this scenario:

driver.h file I have placed this header file at the Arduino.h level so that I can access driver.h file from anywhere.

#pragma once
#ifndef MOTOR_DRIVER_INCLUDED_
#define MOTOR_DRIVER_INCLUDED_

#include<ArduinoSTL.h>
#include<Arduino.h>

class Element {
public:
bool isTLE;

Element() {
isTLE = false;
}
};

class Motor {
public:
Motor() {
Serial.println("Calling the motor constructor");
}
~Motor() {
}
void stopAllBoard();
std::vector<Element*> commandsQueue;
};

static Motor* motor = new Motor;

#endif

driver.cpp file

#include <SPI1.h>

void Motor::stopSomething() {
SPI1.transfer16(0x801);
}

SPI1.h file It is placed at its own standard path.

This is a standard SPI1 library with only minor modifcation in transfer16 function. I am just pushing the command in transfer16 to an queue and printing the address of the object there. Snapshot of SPI1.h file:

....
#include<driver.h>
....
inline static uint16_t transfer16(uint16_t data) {
// My code starts
Element* elem = new Element();
elem->isTLE = true;
motor->commandsQueue.push_back(elem);
Serial.print("Pushed the SPI1 object into the queue with 16bit data. Size queue = ");
Serial.println(motor->commandsQueue.size());
Serial.printf("Motor address at transfer : %x", motor);
Serial.println("");
Serial.print("Size of motor object at transfer: ");
Serial.println(sizeof(motor));
// My code ends


union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
in.val = data;

if (!(SPCR1 & _BV(DORD))) {
  SPDR1 = in.msb;
  asm volatile("nop"); // See transfer(uint8_t) function
  while (!(SPSR1 & _BV(SPIF)));// {Serial.println(data,HEX);}
  out.msb = SPDR1;
  SPDR1 = in.lsb;
  //Serial.println(in.msb,HEX);
  asm volatile("nop");
  while (!(SPSR1 & _BV(SPIF))) ;
  out.lsb = SPDR1;
} else {
  SPDR1 = in.lsb;
  asm volatile("nop");
  while (!(SPSR1 & _BV(SPIF))) ;
  out.lsb = SPDR1;
  SPDR1 = in.msb;
  asm volatile("nop");
  while (!(SPSR1 & _BV(SPIF))) ;
  out.msb = SPDR1;
}
return out.val;
}
....
....

main.cpp

#include<motor_driver.h>

void setup() {
Serial.begin(9600);
Serial.println("");
Serial.printf("Motor address at setup : %x", motor);
Serial.println("");
motor->stopAllBoard();
motor->stopAllBoard();
Serial.print("Commands queue size at the operation start = ");
Serial.println(motor->commandsQueue.size());
Serial.printf("Motor address at setup : %x", motor);
Serial.println("");
}

Output of main.cpp comes out like this in Arduino serial monitor.

18:54:31.008 -> Motor address at setup : 2df
18:54:31.008 -> Pushed the SPI1 object into the queue with 16bit data. Size queue = 1
18:54:31.066 -> Motor address at transfer : 2c4
18:54:31.148 -> Size of motor object at transfer: 2
18:54:31.148 -> ,
18:54:31.148 -> Pushed the SPI1 object into the queue with 16bit data. Size queue = 2
18:54:31.288 -> Motor address at transfer : 2c4
18:54:31.288 -> Size of motor object at transfer: 2
18:54:31.335 -> , ,
18:54:31.335 -> Commands queue size at the operation start = 0
18:54:31.335 ->

If you notice the output, motor address at main.cpp is different than the motor object address in SPI1.h. This means that my vector, considering it as queue. :), does not have right elements in main.cpp.

Out of ideas for this since I do not see any programming issue here. Can anyone suggest a way to move forward. Thank you.

Any more information required?

I think it is this:
This is a global variable which you have defined in a header file:

static Motor* motor = new Motor;

The static key word will hide it from other translation units in which that header file is used, allowing it to be redefined. In other words it is not the same motor.

I understand. Already tried it without using 'static' and the problem remains the same. Removing static makes it a true global variable.

OK. I looked at the problem only at the level that you were printing out the addresses of two different objects and you only expecting to see one.

Anyway, if you want a single global motor object to be used in multiple translation units, do something like this:

// driver.h file
. . .
extern Motor* motor ;
// driver.cpp file
. . .
Motor* motor = new Motor; // instantiate motor 

I hope I've understood what you want to achieve.

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