错误在realloc或free中的消息队列示例中

时间:2012-06-26 06:44:08

标签: c linux realloc

我在消息队列示例中的realloc or free中遇到了一些问题。

在下面的程序中,我从消息队列收到最后一条消息时收到double free or corruption错误。

我在消息队列中发送了10条消息,我在接收方收到10条消息并且工作正常。 收到我正在执行的每条消息后,释放buf指针。它每次都是免费的,但上次提出问题意味着第10次。它给出的错误如double free or corruption在我检查它之前它是如何可能的NULL或者它是否进入,如果条件意味着它不是NULL,那么它是如何给出这样的错误。

还有一件令我惊讶的是,当我收到超过10条消息时,它只发出错误。

如果我发送1到9个消息,它的工作正常。

请让我知道我的代码中的确切问题。

send.c

/*filename   : send.c
 *To compile : gcc send.c -o send
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>


#define SEPRATOR 0X03

struct my_msgbuf
{
    long mtype; /* Message type, must be > 0 */
    char tag[10];
    char messageType[5];
    int messageNumber;
    char sender[64]; 
    char formdata[1]; /* Some compilers allow `char mtext[0]` */
};

int main(void)
{

    int msqid;
    key_t key;
    static int count = 0;
    int sperator = 3;
    int run = 1;
    if ((key = ftok("send.c", 'B')) == -1)
    {
        perror("ftok");
        exit(1);
    }
    printf("send.c Key is = %d\n", key);

    if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1)
    {
        perror("msgget");
        exit(1);
    }
    printf("Enter lines of text, ^D to quit:\n");
    printf("Size of strcuture == %ld\n",sizeof (struct my_msgbuf));
    while (run)
    {
        count++;
        /* Put string in a temporary place */
        char tempformdata[1024];
        char tempSender[64];
        snprintf(tempformdata, sizeof (tempformdata), "%d%cHi hello test message here%c%d%cHi hello test message here%c%d%cHi hello test message here",count,SEPRATOR,SEPRATOR,count,SEPRATOR,SEPRATOR,count,SEPRATOR);
    snprintf(tempSender, sizeof (tempSender), "TESTMEM%cTESTMEM%cTESTMEM",SEPRATOR,SEPRATOR);
        /* +1 for the terminating '\0' */
        size_t msgsz1 = strlen(tempformdata) + 1;
        //size_t msgsz2 = strlen(tempDestination) + 1;
        size_t msgsz2 = strlen(tempSender) + 1;
        /* Allocate structure, and memory for the string, in one go */
        struct my_msgbuf *buf = malloc(sizeof (struct my_msgbuf) + msgsz1);
        /* Set up the message structure */
        buf->mtype = 1;
        memcpy(buf->tag,"TAGVALUES",8);
        memcpy(buf->messageType,"FORM",4);
        buf->messageNumber = 5;
        memcpy(buf->formdata, tempformdata, msgsz1);
        memcpy(buf->sender, tempSender, strlen(tempSender));
        /* And send the message */
        msgsnd(msqid, buf, (sizeof (struct my_msgbuf) + msgsz1- sizeof(long)), 0);
        if (count == 11)
            run = 0;
        usleep(1000000);
    }
    if (msgctl(msqid, IPC_RMID, NULL) == -1)
    {
        perror("msgctl");
        exit(1);
    }
    return 0;
}

receive.c

/* filename   : receive.c
 * To compile : gcc receive.c -o receive
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct my_msgbuf
{
    long mtype; /* Message type, must be > 0 */
    char tag[10];
    char messageType[5];
    int messageNumber;
    char sender[64];    
    char formdata[1]; /* Some compilers allow `char mtext[0]` */
};

int main(void)
{
    size_t msgsz = 8;
    struct my_msgbuf *buf = NULL;
    int msqid;
    key_t key;


    if ((key = ftok("send.c", 'B')) == -1)
    { /* same key as send.c */
        perror("ftok");
        exit(1);
    }

    if ((msqid = msgget(key, 0644)) == -1)
    { /* connect to the queue */
        perror("msgget");
        exit(1);
    }

    printf("test: ready to receive messages, captain.\n");

    for (;;)
    {
        /* Allocate if `buf`  is NULL, otherwise reallocate */
        buf = realloc(buf, msgsz);

        /* Receive message */
        ssize_t rsz = msgrcv(msqid, buf, msgsz, 1, 0);

        if (rsz == -1)
        {
            if (errno == E2BIG)
                msgsz += 8; /* Increase size to reallocate and try again */
            else
            {
                perror("msgrcv");
                break;
            }
        }
        else
        {
            /* Can use `buf->mtext` as a string, as it already is zero-terminated */
            printf("Received message of length %d bytes\n", rsz);
            printf("\tReceived Tag value is             :   %s \n",buf->tag);
            printf("\tReceived Message Type value is    :   %s \n",buf->messageType);
            printf("\tReceived Message Number value is  :   %d \n",buf->messageNumber);
            printf("\tReceived destinations value is    :   %s \n",buf->sender);        
            printf("\tReceived form Data Value is       :   %s \n",buf->formdata);
            if(buf!=NULL)
            {
                printf("\nFree Done in Else\n");
                free(buf);
                printf("\nFree Done in Else 2 \n");
                printf("test \n");
                buf = NULL;
            }

        }
    }
    return 0;
}

输出:

test: ready to receive messages, captain.
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   1Hi hello test message here1Hi hello test message here1Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   2Hi hello test message here2Hi hello test message here2Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
.
.
.
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   9Hi hello test message here9Hi hello test message here9Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
msgrcv: Identifier removed
quipment@ubuntu:~/main/IPC/message_queue$ ./receive
test: ready to receive messages, captain.
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   1Hi hello test message here1Hi hello test message here1Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   2Hi hello test message here2Hi hello test message here2Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   3Hi hello test message here3Hi hello test message here3Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   4Hi hello test message here4Hi hello test message here4Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   5Hi hello test message here5Hi hello test message here5Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   6Hi hello test message here6Hi hello test message here6Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   7Hi hello test message here7Hi hello test message here7Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   8Hi hello test message here8Hi hello test message here8Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 175 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   9Hi hello test message here9Hi hello test message here9Hi hello test message here 

Free Done in Else

Free Done in Else 2 
test 
Received message of length 178 bytes
    Received Tag value is           :   TAGVALUE 
    Received Message Type value is  :   FORM 
    Received Message Number value is    :   5 
    Received destinations value is  :   TESTMEMTESTMEMTESTMEM 
    Received form Data Value is         :   10Hi hello test message here10Hi hello test message here10Hi hello test message here 

Free Done in Else
*** glibc detected *** ./receive: double free or corruption (!prev): 0x0000000001b17010 ***
======= Backtrace: =========
/lib/libc.so.6(+0x775b6)[0x7f5faf6435b6]
/lib/libc.so.6(cfree+0x73)[0x7f5faf649e83]
./receive[0x400986]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f5faf5eac4d]
./receive[0x400719]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:11 5374010                            /home/quipment/main/IPC/message_queue/receive
00600000-00601000 r--p 00000000 08:11 5374010                            /home/quipment/main/IPC/message_queue/receive
00601000-00602000 rw-p 00001000 08:11 5374010                            /home/quipment/main/IPC/message_queue/receive
01b17000-01b38000 rw-p 00000000 00:00 0                                  [heap]
7f5fa8000000-7f5fa8021000 rw-p 00000000 00:00 0 
7f5fa8021000-7f5fac000000 ---p 00000000 00:00 0 
7f5faf3b5000-7f5faf3cb000 r-xp 00000000 08:01 2228303                    /lib/libgcc_s.so.1
7f5faf3cb000-7f5faf5ca000 ---p 00016000 08:01 2228303                    /lib/libgcc_s.so.1
7f5faf5ca000-7f5faf5cb000 r--p 00015000 08:01 2228303                    /lib/libgcc_s.so.1
7f5faf5cb000-7f5faf5cc000 rw-p 00016000 08:01 2228303                    /lib/libgcc_s.so.1
7f5faf5cc000-7f5faf746000 r-xp 00000000 08:01 2231881                    /lib/libc-2.11.1.so
7f5faf746000-7f5faf945000 ---p 0017a000 08:01 2231881                    /lib/libc-2.11.1.so
7f5faf945000-7f5faf949000 r--p 00179000 08:01 2231881                    /lib/libc-2.11.1.so
7f5faf949000-7f5faf94a000 rw-p 0017d000 08:01 2231881                    /lib/libc-2.11.1.so
7f5faf94a000-7f5faf94f000 rw-p 00000000 00:00 0 
7f5faf94f000-7f5faf96f000 r-xp 00000000 08:01 2231874                    /lib/ld-2.11.1.so
7f5fafb4b000-7f5fafb4e000 rw-p 00000000 00:00 0 
7f5fafb6b000-7f5fafb6e000 rw-p 00000000 00:00 0 
7f5fafb6e000-7f5fafb6f000 r--p 0001f000 08:01 2231874                    /lib/ld-2.11.1.so
7f5fafb6f000-7f5fafb70000 rw-p 00020000 08:01 2231874                    /lib/ld-2.11.1.so
7f5fafb70000-7f5fafb71000 rw-p 00000000 00:00 0 
7fffab732000-7fffab747000 rw-p 00000000 00:00 0                          [stack]
7fffab796000-7fffab797000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

1 个答案:

答案 0 :(得分:-1)

在receive.c中,应按以下方式调用realloc:

buf = realloc(buf, msgsz + sizeof(long));

这可以解决您的问题。

此外,在send.c中,你应该在每个msgsnd之后免费拨打电话,当你将数据复制到tagmessageType字段时,你会忘记尾随的'\0'字符 - 你很幸运因为内存归零,但无法保证。