简体   繁体   English

UNIX消息队列分段故障

[英]UNIX message queue segmentation fault

i've got a problem with the exchange of messages between two different process. 我在两个不同进程之间交换消息时遇到问题。 I must use only dynamic arrays. 我必须只使用动态数组。 I also tried using shared memory but i haven't solved my problem. 我也尝试过使用共享内存,但是还没有解决我的问题。

this is the code of the sender: 这是发件人的代码:

  #include <stdio.h>
  #include <string.h>      
  #include <unistd.h>
  #include <stdlib.h> 
  #include <sys/ipc.h>    
  #include <sys/msg.h>    
  #include <errno.h>    
  #define KEYMSG 12345678

typedef struct msg
{
    long int type;
    char* str1;
    char* str2;
}msg;

int main()
{
    msg mymsg;
    mymsg.str1=(char*)malloc(30*sizeof(char));
    mymsg.str2=(char*)malloc(30*sizeof(char));
    strcpy(mymsg.str1,"this is a test ");
    strcpy(mymsg.str2,"test ok ");
    mymsg.type=1;


    if((msgget(KEYMSG,IPC_CREAT|0666))==-1)    
    {
        fprintf(stderr,"ERROR CREATION\n");
        fflush(stderr);
    }
    else
    {
        fprintf(stdout,"CREATION OK\n-----------\n");
        fflush(stdout);
    }

    if((msgsnd(msgget(KEYMSG,0666),&mymsg,sizeof(msg),IPC_NOWAIT))<0)
    {
        fprintf(stderr,"msg not sent\n");
        fflush(stderr);
    }
    else
    {
        fprintf(stdout, "\nmsg sent:\n");
        fprintf(stdout, "%s\t%s\n\n",mymsg.str1,mymsg.str2);
        fflush(stdout);
    }   

and this is the code of the reader: 这是读者的代码:

#include <stdio.h>
#include <string.h>      
#include <unistd.h>
#include <stdlib.h> 
#include <sys/ipc.h>    
#include <sys/msg.h>
#include <errno.h>  
#include <sys/shm.h>
#define KEYMSG 12345678

typedef struct msg
{
    long int type;
    char* str1;
    char* str2;
}msg;

int main()
{
    msg mymsgrcv;
    mymsgrcv.str1=(char*)malloc(30*sizeof(char));
    mymsgrcv.str2=(char*)malloc(30*sizeof(char));

    if((msgrcv(msgget(KEYMSG,0666),&mymsgrcv,sizeof(msg),1,IPC_NOWAIT))==-1)
    {
        fprintf(stderr,"READ ERROR\n");
        fflush(stderr);
    }
    else
    {
        fprintf(stdout, "\nmsg read:\n");
        fprintf(stdout, "%s\t%s\n\n",mymsgrcv.str1,mymsgrcv.str2);
        fflush(stdout);
    }

    return 0;   
}

1.) In your message you have pointers to strings but their addresses are just local to one process. 1.)在您的消息中,您有指向字符串的指针,但它们的地址仅是一个进程的本地地址。 The addresses have no meaning to the other process. 这些地址对其他过程没有意义。 You have to pass the string and not just a pointer to it. 您必须传递字符串,而不仅仅是传递它的指针。

Define the message eg like this: 定义消息,例如:

   typedef struct msg
   {
     long int type;
     char str1[32];
     char str2[32];
   }msg;

2.) Always do error checking on pointers returned by malloc(3) ! 2.)始终对malloc(3)返回的指针进行错误检查!

So you wrote a piece of software under Linux which fails with a segfault. 因此,您在Linux下编写了一个软件,该软件失败并出现段错误。 How to find it? 如何找到它?

First step is to enable debug info in your compiler ( -g in gcc). 第一步是在编译器中启用调试信息(gcc中为-g )。

Then install valgrind. 然后安装valgrind。

Now let's say your program is called homework (so you run it as ./homework ), so run: 现在,假设您的程序称为homework (因此您以./homework运行它),因此运行:

valgrind homework

and valgrind will tell you where the problem is. valgrind会告诉您问题出在哪里。

In the reader part you may get a heap overflow since mymsgrcv.str1 and mymsgrcv.str2 may be empty strings (they do not carry an end char \\0 ). 阅读器部分,由于mymsgrcv.str1mymsgrcv.str2可能为空字符串(它们不带结尾char \\0 ), mymsgrcv.str2可能会导致堆溢出。

You may either use valgrind or gcc address sanitizer (with this compile line: gcc -g -Wall -fsanitize=address -fno-omit-frame-pointer reader.c -o reader ). 您可以使用valgrind或gcc地址清理器(通过以下编译行: gcc -g -Wall -fsanitize=address -fno-omit-frame-pointer reader.c -o reader )。

Here is what gcc address sanitizer reports: 以下是gcc地址消毒剂报告的内容:

==22502==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000effe at pc 0x7fca63d99111 bp 0x7fff4ff40520 sp 0x7fff4ff3fcd0
READ of size 31 at 0x60300000effe thread T0
    #0 0x7fca63d99110  (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x5e110)
    #1 0x7fca63d99a64 in __interceptor_vfprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x5ea64)
    #2 0x7fca63d99b69 in __interceptor_fprintf (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x5eb69)
    #3 0x400c15 in main /home/jvet/TMP/reader.c:32
    #4 0x7fca639b3b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
    #5 0x400988  (/home/jvet/TMP/reader+0x400988)

0x60300000effe is located 0 bytes to the right of 30-byte region [0x60300000efe0,0x60300000effe)
allocated by thread T0 here:
    #0 0x7fca63dcf37a in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x9437a)
    #1 0x400ad7 in main /home/jvet/TMP/p2.c:21
    #2 0x7fca639b3b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)

Whenever you want to send string over IPC, prefer to use array fixed size this will make IPC message of bigger size even though you have very less data to send 每当您想通过IPC发送字符串时,更喜欢使用固定大小的数组,这将使IPC消息的大小更大,即使您要发送的数据很少

To remove such issues you can make tailing of data using variable size array and size of data that is followed by message header. 要消除此类问题,您可以使用可变大小的数组和紧随消息头的数据大小来尾随数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM