通过消息队列接收单个消息时堆栈粉碎

stack smashing when receiving a single message through message queues

我有以下发件人:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>

typedef struct message {
    long int mtype;
    int mtext[200];
} message;

int main(int argc, char *argv[]) {
    // msg queue
    int msgid;
    message msg;
    key_t key;
    
    // create msg queue key
    if ((key = ftok("master.c", 'b')) == -1) {
        perror("ftok");
    }

    // create msg queue
    if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
        perror("msgget");
    }

    msg.mtype=10;
    msg.mtext[0] = 1;
    if ((msgsnd(msgid, &msg, sizeof(message), 0)) == -1) {
        perror("msgsnd");
    }
    sleep(5);

    // TODO: uncomment section
    if (msgctl(msgid, IPC_RMID, NULL) == -1) {
        perror("msgctl");
    }
    
    return 0;
}

接收者:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>

typedef struct message {
    long int mtype;
    int mtext[200];
} message;

int main(int argc, char *argv[]) {
    // msg queue
    message msg;
    int msgid;
    key_t key;
    
    // create msg queue key
    if ((key = ftok("master.c", 'b')) == -1) {
        perror("ftok");
    }

    // create msg queue
    if ((msgid = msgget(key, 0666)) == -1) {
        perror("msgget");
    }

    if ((msgrcv(msgid, &msg, sizeof(message), 10, 0)) == -1) {
        perror("msgrcv");
    }
    printf("%d\n", msg.mtext[0]);

    return 0;
}

问题是当我 运行 他们两个时,我得到

*** stack smashing detected ***: terminated
Aborted (core dumped)

上面的短语是在整个代码按预期执行后显示的,但仍然意味着有些地方不对。但是,如果我将 msgrcv 置于无限循环中,则所有 运行 都按预期 不会发出警告。由于我正在写入和读取相同大小的数据,错误可能来自哪里?

根据 the documentationmsgrcvmsgsz 参数应指示 [=11] 的大小(以字节为单位) =] 消息结构的成员,而不是整个 结构的大小。

该结构通常比可用缓冲区大 4 或 8 个字节(取决于 long int 的定义方式),因此您可能写入超出 available/assigned 内存 - 导致未定义的行为。

该 UB 的一个可能影响是损坏分配给 main 函数的堆栈;如果该函数永远不会 returns(就像添加无限循环时一样),则堆栈损坏 可能 不会自行显现。