Reading array struct in memory

Hi,

I have this struct stored into memory array of 5 elements :

struct StructData
{
  char *deviceID;
  uint8_t packetNum;
  float temperature;
} __attribute__((packed));

StructData sensorRead[5];
int readCnt = 0;

This code fill the array with received data

void storeRTC(StructData &data)
{
  sensorRead[readCnt].deviceID = data.deviceID;       
  sensorRead[readCnt].packetNum = data.packetNum;
  sensorRead[readCnt].temperature = data.temperature;

  // increment read counter
  readCnt++;
}

When I read the array there is the mistery (for me).

All fields are read valids but NOT the data.deviceID, this is always valued as the last filled array element.

void bufferizeData(StructData &data)
{
...
for (int i = 0; i < 5; i++)
    {
        Serial.printf("READ  RTC pos.%i, %s, %i, %.1f\r\n", i, sensorRead[i].deviceID, sensorRead[i].packetNum, sensorRead[i].temperature);
    }
...
}

READ RTC pos.0, C8 FB AC , 218, 24.0
READ RTC pos.1, C8 FB AC , 242, 25.8
READ RTC pos.2, C8 FB AC , 219, 21.0
READ RTC pos.3, C8 FB AC , 220, 24.0
READ RTC pos.4, C8 FB AC , 243, 25.8

The issue is on deviceID (C8 FB AC) wich is always the same but there are multiple nodes transmitting data. All numeric values are correctly related to sensor.

Any suggest ?

Thanks

Show the full code, especially the part that is calling storeRTC.

You use a char pointer, when you should use a char array and strcpy to copy data.deviceID in it

DUMP using strcpy !

// store readings data to RAM RTC
void storeRTC(StructData &data)
{

  Serial.println();
  Serial.printf("BEFORE STORE RTC pos.%i, %s, %i, %.1f, %.1f\r\n", readCnt, data.deviceID, data.packetNum, data.temperature, data.humidity);

  // sensorRead[readCnt].deviceID = data.deviceID;
  strcpy(sensorRead[readCnt].deviceID, data.deviceID); // arg 1 is dest, arg 2 is src

  sensorRead[readCnt].packetNum = data.packetNum;
  sensorRead[readCnt].temperature = data.temperature;
  sensorRead[readCnt].humidity = data.humidity;
  sensorRead[readCnt].pressure = data.pressure;
  sensorRead[readCnt].voltage = data.voltage;

  Serial.printf("AFTER  STORE RTC pos.%i, %s, %i, %.1f, %.1f", readCnt, sensorRead[readCnt].deviceID, sensorRead[readCnt].packetNum, sensorRead[readCnt].temperature, sensorRead[readCnt].humidity);
  Serial.printf(" \u2714\r\n");

  // increment read counter
  readCnt++;
}

BEFORE STORE RTC pos.0, 18 03 0C , 114, 25.9, 45.0
Guru Meditation Error: Core 1 panic’ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x40001406 PS : 0x00060030 A0 : 0x800d2fb6 A1 : 0x3ffb1ec0
A2 : 0x00000000 A3 : 0x3ffc2980 A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x30203831 A9 : 0x3ffb1e10
A10 : 0x00000000 A11 : 0x3ffb1e6c A12 : 0x00000034 A13 : 0x3ffb1eb0
A14 : 0x3ffb1e30 A15 : 0x00000008 SAR : 0x0000001f EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000 LBEG : 0x400013f9 LEND : 0x4000140d LCOUNT : 0xffffffff

struct StructData
{
  char deviceID[10]; // enough space for "XX XX XX " + the null character at the end
1 Like

@guix
Thank’s it work.

READ RTC pos.0, 18 03 0C , 166, 25.9, 45.0
READ RTC pos.1, C8 FB AC , 6, 24.0, 34.0
READ RTC pos.2, C8 FB AC , 7, 21.0, 20.0
READ RTC pos.3, 18 03 0C , 167, 25.9, 44.5
READ RTC pos.4, C8 FB AC , 8, 21.0, 20.0

You copy to a pointer that has no memory backing it up, with luck it is a pointer to some other buffer.

strcpy is a very fragile and error prone method as you had discovered
replace it with the safe strlcpy as in
strlcpy(sensorRead[readCnt].deviceID, data.deviceID, sizeof(sensorRead[readCnt].deviceID));

See this sketch strlcpy_test.ino (7.0 KB) for examples of how to use strlcpy/strlcat strlcpy_P and strlcat_P
and how to detect when your copy overflows the destination buffer and was trancated by strlcpy.

Hi @drmpf , thanks for the sketch. It is useful.

Too bad it will not help you with the bug you introduced,
because it is not connected to buffer overflow, but to buffer non-existence.

strlcpy is for the ‘corrected’ code (#4) to avoid more crashes if deviceID[10] is not large enough.

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