0

I am trying to fill an array (char*).

When I am filling the array, I make a print to display elements and it is OK.

But, after that, when I try to use the array away (in the main() function), always it is filling with the last element.

typedef struct Device {
char *adr_mac;
char *rssi;
} Device; 

Device * devices[6];
int array_length = 6;

void *changeRssi( void *tab)
{
int h = 0;
srand(time(NULL));

int rssi = 0;
char ch[2] = "";

while(1){
   sleep(10);
printf("\n\n  $$$ Changing RSSI of devices ...\n\n");
for (h = 0; h < array_length; h++)
{

    rssi = generate_rssi(10,99);
    sprintf(ch, "%d", rssi);
    devices[h] -> rssi = ch;
    printf("new rssi = %s\n\n", devices[h] -> rssi);
}  
}

}
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • can you also post your main function as well or at least the relevant part that makes use of your array? – Dave S Feb 16 '17 at 10:33
  • The core problem here is that you have an array of pointers. You never do a hard copy of the data, but point at local data. Numerous duplicates about those issues can be found all over SO. – Lundin Feb 16 '17 at 10:34
  • In addition to the linked duplicate, see [Pointer to local variable](http://stackoverflow.com/questions/4570366/pointer-to-local-variable) and [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope). – Lundin Feb 16 '17 at 10:35

1 Answers1

1

There are two things to mention here.

First, It appears, your rssi value takes two chars (range 10-99), but, for sprintf(), you're supplying a buffer of size 2, so you're one element short, or, in other words, you're off-by-one regarding the array bounds.

As per the C11, chapter §7.21.6.6, sprintf() definition

[....]A null character is written at the end of the characters written; [...]

but, in your case, the space is not there, so array boundary overrun happens which invokes undefined behavior.

Solution: you'll be needing an array of size 3.

Second : in case of a statement like devices[h] -> rssi = ch;, the content of ch is not copied to devices[h] -> rssi, rather, the devices[h] -> rssi points to ch. In this case, ch being a local variable, goes out of scope when the function returns, so any later access to devices[h] -> rssi would be an invalid memory access, which, once again, cause UB.

Solution: You need to allocate memory using allocator functions like malloc() and family to devices[h] -> rssi and the copy the content of ch, or, use strdup().

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261