首页 文章

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

提问于
浏览
0

我做了一个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 回答

  • 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不再抱怨 .

相关问题