realloc:下一个大小无效;的memcpy

时间:2013-09-23 18:41:56

标签: c linux sockets memcpy realloc

我有这样的代码:

char buf[128];
char *data = NULL;
char *temp = NULL;

int full = 0;

int n = 0;

do {
     bzero(buf, sizeof(buf));
     n = recv(newsock, buf, sizeof(buf), 0);

     full += sizeof(buf);

     if(n != 0)
          temp = realloc(data, sizeof(buf));

     if(temp != NULL) {
          data = temp;
     } else {
         // error
     }

     memcpy(data + (full - sizeof(buf)), buf, sizeof(buf));

     printf("%s\n",data);
} while(n > 0);

在这段代码中,我尝试从socket到buffer获取一些数据并将这些数据放入内存中。但我有问题。在while循环的第三次迭代中,我得到这样的消息:

*** glibc detected *** ./server: realloc(): invalid next size: 0x09a4c008 ***

当我删除memcpy()函数时一切正常,但我怎样才能将数据放入内存?怎么了?

2 个答案:

答案 0 :(得分:1)

问题是您不断添加数据,但不扩展其内存。这条线

temp = realloc(data, sizeof(buf));

总是分配128个字节。您需要更新它在每次迭代中将分配更多。也许你打算这样做:

temp = realloc(data, full);

答案 1 :(得分:1)

我会使用更像这样的东西:

char buf[128];
char *data = NULL;
char *temp = NULL;
int n, datalen = 0, datacap = 0;

do
{
    n = recv(newsock, buf, sizeof(buf), 0);
    if (n < 0)
    {
        if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
        {
            // error
            break;
        }

        fd_set fdr;
        FD_ZERO(&fdr);
        FD_SET(nwsock, &fdr);

        struct timeval to;
        to.tv_sec = 5;
        to.tv_usec = 0;

        n = select(newsock+1, &fdr, NULL, NULL, &to);
        if (n <= 0)
        {
            // error/timeout
            break;
        }

        continue;
    }

    if (n == 0)
    {
        // disconnected
        break;
    }

    if ((datalen + n) > datacap)
    {
        datacap = ((datalen + n) + (sizeof(buf)-1)) & ~(sizeof(buf)-1);
        // or:
        // datacap = (((datalen + n) + sizeof(buf)) / sizeof(buf)) * sizeof(buf);

        temp = realloc(data, datacap);
        if (temp == NULL)
        {
            // error
            break;
        }

        data = temp;
    }

    memcpy(data + datalen, buf, n);
    datalen += n;

    printf("%*.*s", n, n, buf);
}
while (1);
...
if (data) free(data);