我做了一个C程序,测试并行进程上的一些消息队列 . 消息定义如下:
typedef struct _Message{
long type;
int some_number;
char some_info[SIZE];
}Message;
在我的程序中, msqid
是我使用msgget获取的消息队列的标识符, msg
是Message的一个实例,所有字段都被初始化(超出字符串末尾的所有字符也获得值'\0'以防万一) . 所以我调用msgsnd,指定大小对应于Message而没有该类型的long值('s what I'm应该做什么,对吧?),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 */
};
1 回答
问题可能是你的
_Message
正在与8字节边界对齐(我假设是64位构建,对于32位构建和4字节边界也是如此) .如果
SIZE
是4的奇数倍,则_Message
的整体大小将是8的倍数,您将看到没有问题 .如果
SIZE
是任何其他值,那么_Message
将被填充到下一个8的倍数 . 例如,如果SIZE
是10,那么成员大小的总和是22个字节(并且也没有对齐孔) . 这将被舍入到22,表示结构末尾的2个填充字节 .Valgrind抱怨说这个填充是未初始化的 . 当
memset
实例为零时,成员数据和填充都会被初始化,Valgrind不再抱怨 .