My apologies in advance for the bad-looking code. It's just a proof of concept.
The purpose of the program is to fill the "datapacket", but by individually accessible pointers of the potmeter
struct.
The program works with a complete type of *potPointers[3]
. It also works with incomplete type *potPointer[]
. But then after a successful run, I get:
*** stack smashing detected ***: terminated Aborted (core dumped)
How do I successfully deal with incomplete pointer arrays to a struct?
I can of course put a #define
, but is there another way?
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define BYTES_DATAWORD_POTMETER 2
typedef struct
{
uint8_t test;
uint8_t *datawordPointer[2];
}potmeter;
typedef struct
{
uint8_t amountOfPots;
size_t datapacket_size;
uint8_t *datapacket; // needs to be malloc'ed, don't forget to free it.
// Sort of working with *** stack smashing detected ***: terminated Aborted (core dumped)
potmeter *potPointers[];
// Works without stack smashing.
// potmeter *potPointers[3];
}overall;
void initPointersToDatapackett(overall *allePots)
{
uint8_t counter = 0;
for(int i = 0; i < allePots->amountOfPots; i++)
{
// Allocate memory per pot
allePots->potPointers[i] = malloc(sizeof(potmeter));
// Point pointers to dataword of overall
allePots->potPointers[i]->datawordPointer[0] = &allePots->datapacket[counter++];
allePots->potPointers[i]->datawordPointer[1] = &allePots->datapacket[counter++];
}
}
int main()
{
overall AllePotMeters;
AllePotMeters.amountOfPots = 3;
AllePotMeters.datapacket = malloc(AllePotMeters.amountOfPots*BYTES_DATAWORD_POTMETER);
initPointersToDatapackett(&AllePotMeters);
//Test content of pointers to dataword
*AllePotMeters.potPointers[0]->datawordPointer[0] = 'A';
*AllePotMeters.potPointers[0]->datawordPointer[1] = 'B';
*AllePotMeters.potPointers[1]->datawordPointer[0] = 'C';
*AllePotMeters.potPointers[1]->datawordPointer[1] = 'D';
*AllePotMeters.potPointers[2]->datawordPointer[0] = 'E';
*AllePotMeters.potPointers[2]->datawordPointer[1] = '\0';
printf("String test %s\n", AllePotMeters.datapacket);
free(AllePotMeters.potPointers[0]);
free(AllePotMeters.potPointers[1]);
free(AllePotMeters.potPointers[2]);
free(AllePotMeters.datapacket);
return 0;
}
The feature you are using here is called "flexible array member". If the array size is empty, the size of the overall
struct doesn't include the array at all. So a variable of overall
type doesn't contain any memory for your potPointers
.
It's programmer's responsibility to allocate space for potPointers
. Note that this usually means allocating the struct
dynamically, using malloc
. Then, you (the programmer) can tell it to allocate more memory than sizeof(overall)
.
For example:
overall *AllePotMeters = malloc(sizeof(overall) + 3 * sizeof(potmeter *));
If AllePotMeters
is on stack, the compiler doesn't allocate any memory at all for the flexible array member. So writing to it smashes the stack (i.e. overwrites important data on stack).