我制作了一个C程序,用于测试并行进程上的一些消息队列。消息的定义如下:
typedef struct _Message{
long type;
int some_number;
char some_info[SIZE];
}Message;
在我的程序中,msqid
是我使用msgget获取的消息队列的标识符,而msg
是Message的一个实例,所有字段都被初始化(所有字符都超出了字符串也得到值'\ 0'以防万一)。所以我调用msgsnd,指定大小对应于没有类型的长值的消息(这是我应该做的,对吗?),并且0表示标志,所以它等待发送消息。
msgsnd(msqid, &msg, sizeof(Message) - sizeof(long), 0);
程序运行正常,数据正确发送,另一个进程接收它并正确打印所有内容。但是,Valgrind大师并不这么认为:
==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==
msgsnd的官方文档讨论了一个struct msgbuf,其中包含一个名为mtext的字段,但我真的不明白它的含义,它如何与我自定义的Message结构相对应,以及我是如何设法给它的一个值。那么,关于如何解决这个问题的任何想法?
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
答案 0 :(得分:0)
问题可能是你的_Message
正在与8字节边界对齐(我假设64位构建,对于32位构建和4字节边界也是如此)。
typedef struct _Message{
long type; // 8 bytes
int some_number; // 4 bytes
char some_info[SIZE]; // SIZE bytes
}Message;
如果SIZE
是4的奇数倍,则_Message
的整体大小将是8的倍数,您将看到没有问题。
如果SIZE
是任何其他值,则_Message
将填充到下一个8的倍数。例如,如果SIZE
为10,那么成员的大小总和为22个字节(并且没有对齐孔)。这将向上舍入为22,表示结构末尾的2个填充字节。
Valgrind抱怨说这个填充是未初始化的。当你将实例memset
置零时,会员数据和填充都会被初始化,Valgrind不再抱怨。