I have initialized a structure inside my C program and attached it to the Shared memory. The structure is as below:
#define DrvMaxTag 1024
#define DrvMaxStr 128
#define StructLEN 32
typedef struct TagTypeStruct
{
unsigned char IO;
unsigned char Drv;
unsigned char Class;
unsigned char Group;
}TagTypeStruct;
typedef struct IEC_DT
{
long int tv_Sec;
long int tv_nSec;
}IEC_DT;
typedef struct DrvSHMTagStruct
{
char TagName[DrvMaxTag][DrvMaxStr];
double TagValue[DrvMaxTag];
double OldValue[DrvMaxTag];
unsigned int TagStatus[DrvMaxTag];
unsigned int OldStatus[DrvMaxTag];
long long TagControl[DrvMaxTag];
IEC_DT TagValueDT[DrvMaxTag];
TagTypeStruct TagType[DrvMaxTag];
int DrvAddr[DrvMaxTag];
unsigned char LogFlag[DrvMaxTag];
unsigned char Freeze[DrvMaxTag];
int LogicState;
char DrvPath[DrvMaxStr];
int TagQuantity;
unsigned char Instance;
}DrvSHMTagStruct;
I'm trying to read the structure from another program that is written in Golang. I have calculated how many bytes each field takes in C and have an equivalent field for it inside my Golang structure which is as below:
const StructLEN = 32
const DrvMaxTag = 1024
const DrvMaxStr = 128
type TagTypeStruct struct {
IO uint8
Drv uint8
Class uint8
Group uint8
}
type IEC_DT struct {
tv_Sec int32
tv_nSec int32
}
type DrvSHMTagStruct struct {
TagName [DrvMaxTag][DrvMaxStr]byte
TagValue [DrvMaxTag]float64
OldValue [DrvMaxTag]float64
TagStatus [DrvMaxTag]uint32
OldStatus [DrvMaxTag]uint32
TagControl [DrvMaxTag]int64
TagValueDT [DrvMaxTag]IEC_DT
TagType [DrvMaxTag]TagTypeStruct
DrvAddr [DrvMaxTag]int32
RetainFlag [DrvMaxTag]uint8
Freeze [DrvMaxTag]uint8
LogicState int32
DrvPath [DrvMaxStr]uint8
TagQuantity int32
Instance uint8
}
The size of the structure (DrvSHMTagStruct
) in C is 182416 and in Golang is 182412 (my OS is ARM-based). So why the difference? They are different in 4 bytes and the interesting part is that they are both working perfectly, reading and writing on the same structure without a mistake.
As I obviously searched about it, I understood that the C compiler does some Data Structure alignment during the compilation process. Hence, the 4 bytes difference. But the question is how does the Golang program read the structure from the shared memory correctly even though it has a 4-byte difference?
Also, the problem emerges when I run the programs on my ARM-based Linux. They are the same size when on a x64 Ubuntu.
It's the padding of the last member, Instance
. In your C version, it gets padded with 7 bytes. In the Go version it gets padded with 3. The difference is the 4 bytes you notice when doing sizeof
on the two platforms.
In order to make them the same, you can possibly #pragma pack(4)
in the the C version or #pragma pack(8)
in the Go version (if it even supports packing, a search suggests that it doesn't) or add a filler as a last member to the Go struct:
Filler1 [7]uint8