Reputation: 21
I made a C program that tests some message queues on parallel processes. The messages are defined like this:
typedef struct _Message{
long type;
int some_number;
char some_info[SIZE];
}Message;
In my program, msqid
is the identifier of the message queue that I obtain with msgget, and msg
is an instance of Message for which all fields are initialised (all chars beyond the end of the string also get the value '\0' just in case). So I call msgsnd, specifying that the size corresponds to Message without the long value for the type (that's what I'm supposed to do, right?), and 0 for the flag so it waits to send the message.
msgsnd(msqid, &msg, sizeof(Message) - sizeof(long), 0);
The program works just fine, the data is sent correctly and another process receives it and prints everything correctly. However, Master Valgrind doesn't see it that way:
==3514== Syscall param msgsnd(msgp->mtext) points to uninitialised byte(s)
==3514== at 0x4F368F3: __msgsnd_nocancel (syscall-template.S:81)
==3514== by 0x400E9D: func_a ......
==3514== by 0x4011CB: main ......
==3514== Address 0xfff00002c is on thread 1's stack
==3514== in frame #1, created by func_a (???)
==3514==
The official documentation for msgsnd talks about a struct msgbuf, which contains a field called mtext, but I don't really understand what it means, how it corresponds to my customised struct for Message and how I'm suppossed to give it a value. So, any ideas on how to solve this?
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
Upvotes: 2
Views: 1602
Reputation: 6916
The issue is probably that your _Message
is getting aligned to an 8 byte boundary (I'm assuming a 64bit build, the same would be true for 32bit builds and 4byte boundaries).
typedef struct _Message{
long type; // 8 bytes
int some_number; // 4 bytes
char some_info[SIZE]; // SIZE bytes
}Message;
If SIZE
is an odd multiple of 4 then the overall size of _Message
will be a multiple of 8 and you will see no problem.
If SIZE
is any other value then the _Message
will get padded to the next multiple of 8. For instance if SIZE
is 10 then the sum of the size of the members is 22 bytes (and there are no alignment holes as well). This will be rounded up to 24 meaning 2 padding bytes at the end of the struct.
Valgrind is complaining that this padding is uninitialized. When you memset
the instance to zero then both the member data and the padding get initialized and Valgrind no longer complains.
On the Valgrind side it isn't easy to fix this. Syscalls like this take pointers to anything and Valgrind can't tell whether uninitialized bytes are a genuine error or whether they are holes/padding in structures. One possibility would be to generate a lower level of warning for uninitialized ranges that are less than the word size.
Upvotes: 2