2016-01-24 68 views
-1

我遇到了兩個不同進程之間交換消息的問題。 我只能使用動態數組。 我也試過使用共享內存,但我還沒有解決我的問題。UNIX消息隊列分段錯誤

這是發件人的代碼:

#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); 
    } 

,這是讀者的代碼:

#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; 
} 
+0

我們都坐在座位邊緣試圖找出你的問題! –

+0

您是否嘗試過使用'-g'選項編譯此代碼,然後運行'valgrind。/ /程序名稱? Valgrind會告訴你更多關於正在發生的事情的信息。如果你使用'yum',你可以在Ubuntu上用'sudo apt-get install valgrind'安裝Valgrind,並且可能'yum install valgrind'。 – conradkdotcom

回答

2

1)在你的消息,你有指向字符串但他們的地址是隻是一個進程的本地。這些地址對其他進程沒有意義。 你必須傳遞字符串,而不僅僅是一個指向它的指針。

定義消息例如像這樣:

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

2.)總是對由malloc(3)返回的指針進行錯誤檢查!

+0

感謝您的答案,這種方式,但我不能定義任何非動態數組即使在msg結構。 有什麼建議嗎?謝謝 –

+0

在'msgsnd()'中指定消息的長度。因此你可以使用malloc()任意大小。定義這樣的消息 'typedef struct msg { long int type; char str []; 'msg * mymsg = malloc(sizeof(msg)+ length_of_string);'。 – Bernhard

0

所以你寫的Linux下的軟件,其失敗段錯誤。如何找到它?

第一步是使你的編譯器調試信息(-g在GCC)。

然後安裝的valgrind。

現在讓我們假設你的程序被稱爲homework(因此可以將其作爲./homework),這樣運行:

valgrind homework 

和Valgrind的會告訴你哪裏出了問題。

0

讀者部分,你可能會得到一個堆溢出,因爲mymsgrcv.str1mymsgrcv.str2可以爲空字符串(不帶有結束字符\0)。

可以選擇使用的valgrind或洗手液GCC地址(這個編譯行:gcc -g -Wall -fsanitize=address -fno-omit-frame-pointer reader.c -o reader)。

下面是GCC地址消毒劑報道:每當你想通過IPC發送字符串,

==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) 
+0

對不起,但這個答案是巫毒魔法。在玩像valgrind這樣的工具之前,你應該看看代碼。 – Bernhard

0

喜歡使用數組大小​​固定,這將使得即使你有非常少的數據,以更大尺寸的IPC消息發送

爲了除去這樣的問題就可以使使用可變大小陣列和數據的大小後跟消息報頭數據的拖尾。