Two global objects sharing the same memory location

I am having a problem with two global scope objects being assigned the same memory address by the compiler. One is a class instance (accelHighG in the code below) and one is an array of floats (accelOffsetErrors[] in the code below). When I print the address of accelOffsetErrors[0] and the address of accelerationReading[2] (a private data member of the accelHighG object) they are both at address 0x200002C8. This, of course, is leading to problems when the program runs. I have included a reduced version of my program below that still demonstrates the issue. I have also included the .h file for the H3LIS331 class. Any ideas as to what I might be doing wrong to cause this?

I am using Arduino IDE 2.3.2 and an Adafruit Feather M0 RFM95.

This is the program code:

// ==============================  Include Files  ==================================
#include <SPI.h>                 // Sensor and micro SD card communication
#include <SD.h>                  // SD card library functions
#include <BMP3XX.h>              // BMP390 sensor library code
#include <LSM6DSO32.h>           // LSM6DSO32 sensor library code
#include "wiring_private.h"      // pinPeripheral() function
#include "RTClib.h"              // Real Time Clock library by Adafruit
#include <RWP_GPS.h>             // GPS Library
#include <RH_RF95.h>             // Radio Head driver class for LoRa Radio
#include <RHReliableDatagram.h>  // Radio Head manager class for reliable comms
#include <H3LIS331.hpp>          // H3LIS331 sensor library code
#include <Arduino.h>
#include <ArduinoJson.h>  // JASON file support for app settings
#include <lowPassFilter.h>

// ===============================  Constants  =====================================

#define GPSSerial Serial1

// Feather M0 pin assignments
const uint8_t H3LIS331_CS = SDA;     // PA22
const uint8_t RADIO_SPI_CS = 8;      // PA06
const uint8_t RADIO_SPI_IRQ = 3;     // PA09
const uint8_t SENSOR_SPI_CLK = 12;   // PA19
const uint8_t SENSOR_SPI_MOSI = 10;  // PA18
const uint8_t SENSOR_SPI_MISO = 11;  // PA16

// Other Global Constants

const uint8_t MAX_MESSAGE_LENGTH = 20;  // Maximum LoRa radio message length

enum states { START_UP,
              FAULT,
              READY,
              ARMED,
              LOGGING,
              POST_FLIGHT,
              GOTO_ARM,
              GOTO_LOGGING,
              GOTO_POST_FLIGHT,
              GOTO_READY };
enum errors { NONE,
              GYRO,
              ACCEL,
              ALT,
              BATTERY
};

// Struct to hold the app parameters that are set via the SD card settings file
struct Settings {
  double bat1VoltLow;                 // 3.7v LiPo battery voltage threshold for low charge
  double bat1VoltOK;                  // 3.7V LiPo battery voltage threshold for medium charge
  double bat1VoltFull;                // 3.7V LiPo battery voltage threshold for full charge
  bool bat2Present;                   // True: External event battery installed
  double bat2VoltLow;                 // 7.4V LiPo battery voltage threshold for low charge
  double bat2VoltOK;                  // 7.4V LiPo battery voltage threshold for medium charge
  double bat2VoltFull;                // 7.4V LiPo battery voltage threshold for full charge
  uint8_t parachute;                  // 0: function not used; 1 to 4: The event to use for this function
  uint16_t parachuteReleaseDelay;     // Delay in milliseconds from appogee to parachute release
  uint8_t drogueParachute;            // 0: function not used; 1 to 4: The event to use for this function
  uint16_t drogueChuteReleaseDelay;   // Delay in milliseconds from parachute release to drogue chute release
  uint8_t secondStage;                // 0: function not used; 1 to 4: The event to use for this function
  uint16_t secondStageIgnitionDelay;  // Delay in milliseconds from first stage burnout to second stage ignition
  uint8_t firstStateIgnition;         // 0: function not used; 1 to 4: The event to use for this function
  double seaLevelPressure;            // Atmospheric pressure at sea level
  double launchAccelThreshold;        // Acceleration level above which a launch will be detected
  double landedThreshold;             // Axial rotation rate below which a landing will be detected
  int flightTimeout;                  // Time after which we will assume we have landed if landing has not been detected (seconds).
  uint8_t upGoVAddr;                  // LoRa radio address of this UpGoV avionics instance
  bool groundTest;                    // True: Ground test mode activated.
};

// ===================================  Global Objects  ===================================================

SPIClass sensorSPI(&sercom1, 11, 12, 10, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0);  // The sensor SPI bus instance
BMP3XX altimeter;                                                            // Altimeter sensor object instance
LSM6DSO32 accelerometer_gyro;                                                // Accelerometer/Gyro sensor object instance
H3LIS331 accelHighG;                                                         // H3LIS331 high accelerometer object instance
RH_RF95 radioDriver(RADIO_SPI_CS, RADIO_SPI_IRQ);                            // LoRa radio driver object
RHReliableDatagram radioManager(radioDriver);                                // LoRa radio manager object
Adafruit_GPS gps(&GPSSerial);                                                // GPS object
File dataFile;                                                               // Data file object
File logFile;                                                                // Log file object
Settings settings;                                                           // Application settings
LowPassFilter xAxisAccel;                                                    // Filter for x-axis acceleration reading
LowPassFilter altitudeFilter;                                                // Filter for altitude reading
LowPassFilter xAxisHighGAccel;                                               // Filter for the high G accelerometer

// ================================ Global Variables ======================================================

volatile bool rtcInterruptFlag = false;         // Flag set by rtc interrupt handler
double temperature = 0.0;                       // Temperature in degrees C as measured by the BMP390 sensor
double pressure = 0.0;                          // Pressure in hpa as measured by the BMP390 sensor
double altitude = 0.0;                          // Altitude in meters as measured or computed from the BMP390 sensor
int8_t altErrCode = 0;                          // Result code returned from BMP390 API calls
bool dataFileOpen = false;                      // Flag to indicate dataFile state
uint32_t launchTime = 0;                        // Time at launch in millisends
states state = START_UP;                        // The current state
errors error = NONE;                            // Error
double maxAcceleration = 0.0;                   // The maximum X-Axis acceleration measured during flight
double maxAltitude = 0.0;                       // The maximum altitude measured during flight
uint32_t flightLength = 0;                      // The flight duration (launch to landing) in seconds
double velocity = 0.0;                          // The computed velocity
double maxVelocity = 0.0;                       // The maximum computed velocity during flight
uint32_t prevTime = 0;                          // Previous time measurement used by velocityCalculator() ms
double prevAcc = 0.0;                           // Previous acceleration measurement used by velocityCalculator() ft/sec2
double prevVelocity = 0.0;                      // Previous calculated velocity used by velocityCalculator() ft/sec
bool gpsFix = false;                            // Flag indicating if a GPS fix has been made
double launchPointLat = 0.0;                    // Launch point lattitude as obtained from GPS
double launchPointLon = 0.0;                    // Launch point longitude as obtained from GPS
double launchPointAlt = 0.0;                    // Altitude above MSL in meters as obtained from GPS
double baroAltitudeError = 0.0;                 // Difference between baro computed alt and GPS alt
uint8_t buffer[MAX_MESSAGE_LENGTH];             // LoRa radio message buffer
int radioError = 0;                             // The number of radio messages not receiving an ack
float accelOffsetErrors[] = { 0.0, 0.0, 0.0 };  // Accelerometer zero offset errors
float gyroOffsetErrors[] = { 0.0, 0.0, 0.0 };   // Gyro zero offset erros
float highG_AccelOffsetError = 0.0;             // X Axis offset error for the high G Accel
uint32_t apogeeTime = 0;
uint32_t drogueChuteReleaseTime = 0;
uint32_t parachuteReleaseTime = 0;
uint32_t firstStageEngineBurnoutTime = 0;
uint32_t secondStageIgnitionTime = 0;
bool landed = false;
uint32_t landingTime = 0;

// =============================  Setup Function  ===================================
void setup() {
  Serial.begin(115200);  // Make sure the Serial Monitor is set to 115200 baud
  while (!Serial) {
    ;
  }

  // ======================  Initialize the Sensor SPI Bus  ============================
  sensorSPI.begin();
  pinPeripheral(10, PIO_SERCOM);
  pinPeripheral(11, PIO_SERCOM);
  pinPeripheral(12, PIO_SERCOM);

  accelHighG.begin(H3LIS331_CS, &sensorSPI);

  Serial.print("accelOffsetErrors[0] address: ");
  Serial.println((uint32_t)&accelOffsetErrors[0], HEX);
  accelHighG.getAcceleration();


}  // End setup code

void loop() {
}

This is the .h file code for the H3LIS331 class.

class H3LIS331 {
public:
    //Constructor
    H3LIS331();
    
    //Initialization
    bool begin(uint8_t cs, SPIClass *spiPtr = &SPI, uint32_t spiFrequency = DEFAULT_SPI_FREQ);
    
    //Configuration
    void setRange(h3lis331dl_fs_t range);
    h3lis331dl_fs_t getRange(void);
    void setOutputDataRate(h3lis331dl_dr_t ODR);
    h3lis331dl_dr_t getOutputDataRate(void);
    void enableAxis(h3lis331_axis_t axis);
    h3lis331_axis_t getEnabledAxis(void);
    void setBlockDataUpdate(void);
    void clearBlockDataUpdate(void);
    bool blockDataUpdateEnabled(void);
    
    //Interrupt configuration
    void setInterruptPinsConfig(h3lis331dl_i1_cfg_t pin1Source, h3lis331dl_i2_cfg_t pin2Source,
                                bool latched = false, bool activeHigh = true, bool pushPull = true);
    void interrupt1Config(uint8_t eventsEnabled, bool orEvents,
                          uint8_t threshold, uint8_t duration);
    void interrupt2Config(uint8_t eventsEnabled, bool orEvents,
                          uint8_t threshold, uint8_t duration);
    
    //Accelerometer Data
    h3lis331dl_status_reg_t getStatus(void);
    bool isDataReady(void);
    float getX_Accel(void);
    float getY_Accel(void);
    float getZ_Accel(void);
    void getAcceleration(void);
    h3lis331dl_int1_src_t getInterrupt1Source();
    h3lis331dl_int2_src_t getInterrupt2Source();
    bool isInt1Active();
    bool isInt2Active();
    
    
private:
    bool _init(void);
    stmdev_ctx_t sensorAPI_intf;    // Structure holds pointers to spi read/write functions
                                    // and spi bus object
    h3lis331dl_fs_t accelRange;
    float accelerationReading[3];   // X, Y, and Z axis acceleration in Gs
    
};

That's still a huge amount of code. There's no way I'm hunting down and installing all those libraries in order to test compile your code. Also, you only included the header file for the H3LIS331 class, not the implementation file. So again, no way to test compile your code.

Please, try again. Get rid of the all the extraneous clutter and post a true MRE. That's the smallest possible, complete code that demonstrates the problem at hand.

I don't see it printing the two addresses you speak of.

a7

So sorry for the verbose code. This is my first post so I'm learning here. I guess I never assumed that someone would try to compile and run my code to try to duplicate the issue. Rather, I was hoping that someone might have some ideas about why the compiler would place global objects in the same memory locations. The kind of errors that might lead to this.

I will just continue to try to boil this down to a more concise description.

Unless the question is trivial (and yours isn’t), I typically don’t give coding advise unless I can, at the very least, test compile any solutions I propose. Preferably I’m able to actually test the solution, if I have the hardware. If not, I make the statement: “Compiles But Untested”.

It is somewhat quite unlikely that the compiler would assign the same adddress to two different and unrelated elements. So there must be something going on somewhere in the code.