我编写了一个C程序,测试并行进程上的一些消息队列。消息的定义如下:
typedef struct _Message{
long type;
int some_number;
char some_info[SIZE];
}Message;
在我的程序中,msqid
是使用msgget获得的消息队列的标识符,msg
是Message的一个示例,它的所有字段都已初始化(为了以防万一,字符串末尾以外的所有字符也将得到值'\0'),所以我调用msgsnd,指定size对应于没有类型long值的Message(这就是我应该做的,对吗?),0表示标志,这样它就可以等待发送消息。
msgsnd(msqid, &msg, sizeof(Message) - sizeof(long), 0);
程序运行得很好,数据发送正确,另一个进程接收数据并正确打印所有内容,但瓦尔格林大师并不这么看:
==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的字段,但我不太明白它的意思,它如何与我定制的消息struct相对应,以及我应该如何给予它一个值。
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
1条答案
按热度按时间ubof19bj1#
问题可能是您的
_Message
与8字节边界对齐(我假设是64位构建,32位构建和4字节边界也是如此)。如果
SIZE
是4的奇数倍,那么_Message
的总大小将是8的倍数,您将不会看到任何问题。如果
SIZE
是任何其他值,则_Message
将被填充到8的下一个倍数。例如,如果SIZE
是10,则成员的大小之和是22字节(也没有对齐孔)。这将被舍入到22,意味着在结构的末尾有2个填充字节。Valgrind抱怨此填充未初始化。当您将示例
memset
为零时,成员数据和填充都会初始化,Valgrind不再抱怨。在Valgrind方面,修复这个问题并不容易。像这样的系统调用接受指向任何东西的指针,Valgrind无法判断未初始化的字节是真正的错误还是结构中的漏洞/填充。一种可能性是对小于字长的未初始化范围生成一个较低级别的警告。