I have several nested structures within a parent structure in a header file like so:
struct Treatment {
unsigned char num_phases;
unsigned char duration[6];
unsigned char max_current[3];
struct Phase{
unsigned char duration[6];
unsigned char start_delay;
unsigned char ramp_up_threshold;
unsigned char ramp_up[3];
unsigned char contraction[4];
unsigned char ramp_down_threshold;
unsigned char ramp_down;
unsigned char relaxation;
unsigned char end_delay;
unsigned char frequency;
unsigned char time[3];
struct Pulse{
unsigned char type;
unsigned char bipolar_gap[3];
unsigned char num_timeslots;
unsigned char pre_pulse_delay[5];
struct Timeslot{
unsigned char duration[3];
unsigned char dead_time[2];
unsigned char amplitude[3];
unsigned char electrodes_1_2[2];
unsigned char electrodes_3_4[2];
} timeslots[20];
} pulses[10];
} phases[5];
};
I'm creating an instance of the parent structure in a source file like so (and including the header file of course):
struct Treatment treatment = {0};
I am running the code in debug mode using J-LINK on an STM32 in a Keil project. I am getting a hard fault exception due to the inner most structure in the parent structure:
struct Timeslot{
unsigned char duration[3];
unsigned char dead_time[2];
unsigned char amplitude[3];
unsigned char electrodes_1_2[2];
unsigned char electrodes_3_4[2];
} timeslots[20];
When I remove this inner structure the code runs fine. I'm not getting any build errors.
The hard fault occurs at a function that uses the parent structure:
parseMessage(TR, &message[0], treatment);
Can anyone help me with this? I have no idea why the debugger does not like the inner structure.
Cheers, Tony
You have so many nested arrays of structs that each struct Treatment
is 12625 B in size (assuming that it's packed). Removing that inner array of structs reduces the size by 12 kB to just 625 B which, while still large, is reasonable.
When you pass a struct to a function, it pushes it to the stack before calling the function, so there's a fairly good chance that you're running out of stack space, and are experiencing a stack overflow. If you need to use this struct, create a function that uses pointers: (Guessing at the other types involved, you would use the actual ones)
// Function declaration
void parseMessage(int, char *message, struct Treatment *treatment);
// Function usage
parseMessage(TR, &message[0], &treatment);
One thing to consider is that a struct passed to a function by value will be copied, so any changes done to the scruct will only exist in that copy within the function. When the function exits, that copy is deleted, and any changes made during the function execution are gone. If you want to make changes to the original struct, then method written out above should work. If you don't need to make any changes to the struct at any time, then you can use a function like:
void parseMessage(int, char *message, struct Treatment const *treatment);
You will not be able to modify the contents of the struct pointed to by treatment
, and the compiler should yell at you if you try to do so.
If the nature of the function is that you make changes to the struct, but want those changes to disappear after the function ends, then the only reasonable method would be to make a copy of it. Since it seems to be too big for the stack, you would have to create a dynamic allocation using malloc
, memcpy
the data to the new copy, do your operations, then free
it. This will however use a lot of space in the heap, and I would not be surprised to see the call to malloc
fail (return a NULL
).