2017-08-09 40 views
0

我寫了兩個程序一個用msgsnd發送消息和其他用msgrcv接收。我已經使用了這些功能很長一段時間,但我無法弄清楚在接收文件時發現「stack smashing detected」錯誤。在該文件中,我嘗試將文件的一部分複製到一個char數組,將第二部分複製到第二個數組中。如果在文件中調用msgrcv,我會在接收程序完成後檢測到堆棧粉碎。在一個文件的末尾,我調用printf函數來打印兩個數組。從我的觀點來看,arr1和arr2應該包含完整的消息,而只有arr1包含消息,而arr2是空的。但最大的問題是堆棧粉碎檢測到的錯誤。我把代碼如下兩個文件:調用msgrcv函數後檢測到堆棧粉碎

發送文件:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <math.h> 
#include <string.h> 
#include <sys/mman.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/sem.h> 
#include <sys/msg.h> 
#include <stdint.h> 

typedef struct message { 
    long type; 
    char text[128]; 
} message; 

int main (int argc, char **argv) { 
    if (argc == 3 && strcmp (argv [1], "-m") == 0) { 
    key_t key = (key_t) atoi (argv[2]); 
    message msg; 
    int message_queue_id = msgget (key, IPC_CREAT | 0666); 
    int semaphore_set_id = semget (key, 1, IPC_CREAT | 0666); 
    struct semid_ds buf; 
    struct sembuf sb; 
    long long buf_address = (long long)&buf; 
    long long sb_address = (long long)&sb; 
    // sending message 
    msg.type = 6; 
    memset (msg.text, 0, 128); 
    printf ("%p %p\n", (void*)&buf, (void*)&sb); 
    sprintf (msg.text, "%lld %lld", buf_address, sb_address); 
    printf ("msg: %s\n", msg.text); 
    void* ptr = (void*)buf_address; 
    printf ("ptr = %p\n", ptr); 
    msgsnd(message_queue_id, (struct msgbuf*)&msg, sizeof (msg) - 4, 0); 
    sleep (1000); 
    } 
} 

接收文件(無頭):

typedef struct message { 
    long type; 
    char text[128]; 
} message; 

int main (int argc, char **argv) { 
    if (argc == 3 && strcmp (argv [1], "-m") == 0) { 
    key_t key = (key_t) atoi (argv[2]); 
    int message_queue_id = msgget (key, IPC_CREAT | 0666);; 
    int semaphore_set_id = semget (key, 1, IPC_CREAT | 0666); 
    message msg; 
    struct semid_ds buf; 
    struct sembuf sb; 
    msgrcv (message_queue_id, (struct msgbuf*)&msg, sizeof(msg) - 4, 6, IPC_NOWAIT); 
    printf ("msg = %s\n", msg.text); 
    char arr1[32] = "\0", arr2[32] = "\0"; 
    int i = 0; 
    while (msg.text[i] != ' ') { 
     arr1[i] = msg.text[i]; 
     i++; 
    } 
    i++; 
    while (msg.text[i]) { 
     arr2[i] = msg.text[i]; 
     i++; 
    } 
    printf ("arr1 = %s, arr2 = %s\n", arr1, arr2); 
    printf ("sizeof(long) = %d\n", (int)sizeof(long)); 
    } 
} 
+0

我不喜歡這樣的樣子:'(long long)&buf;'鑄造一個長長的指針 –

+0

特別是因爲它是有符號的值。不太適合指針 –

回答

1
msgrcv (message_queue_id, (struct msgbuf*)&msg, sizeof(msg) - 4, 6, IPC_NOWAIT); 

msgrcv的第三個參數應該是大小緩衝區存儲在消息結構中。在計算sizeof(msg) - 4時,您似乎認爲long的大小始終爲4,這是不正確的。相反,你應該簡單地使用sizeof(msg.text)

您在發件人中也有同樣的錯誤。因爲在64位linux中long的大小是8個字節而不是4個,所以你的代碼將會在msg變量的末尾寫入,導致緩衝區溢出。