Syscall param msgsnd(msgp-> mtext)指向未初始化的字节 - 消息队列 - Valgrind

时间:2018-04-22 11:34:07

标签: c valgrind message-queue

我制作了一个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 */
  };

1 个答案:

答案 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不再抱怨。