Today i was working on a structure that looked like this
struct a_{U8bit i;U8bit data[0];};typedef a_ a_t;As can be seen the 'data' is an expandable array. This was used to point to another structure say b_t;
typedef struct b_{int integer;}b_t;a_t *a;b_t *b; // another structure of arbitrary typememcpy(a->data, b, sizeof(b));Assume that the memory location of structure 'a' is 200 and that of 'b' is '210'. Now since the first element of 'a' is of size 1 byte, the statement
memcpy(a->data, b, sizeof(b)); had copied the structure 'b' to the memry location 201. Everything seemed to go well till now. but when i tried to unpack the intger of 'b' structure from 'a' structure I got a Segmentation Fault. (OS: Solaris ). This is because i was trying to read the integer from an memory location
that was not a muliple of 4.
Purify categorises this as
Misaligned Memory Read.
With the knowledge i have today, this can be avoided in two ways.
1. The structure declaration of a_t shud be like this
struct a_{ U8bit data[0]; U8bit i; }; The parameter 'i' has been moved down to prevent misalignment of the structure to be packed into 'data' field
2. Using memcpy.
Say we wanna use this statement..
int temp = (b_t *)(a->data)->integer;
This will result in a Segmentation fault. Instead use a temporary struture of type b_t, memcpy a->data into it and then use it.
b_t *temp_struct;
temp_struct = (b_t *)malloc(sizeof(b_t)); // This structure will be properly alligned
memcpy(temp_struct, a->data, sizeof(b_t));
temp = temp_struct->integer.
This wud do the trick .
Sometimes (as was the case with me), the solution 1 wont be plausible. In my case, I dint want the structure definition to change.