【问题标题】:realloc()ing memory for a buffer used in recv()realloc() 为 recv() 中使用的缓冲区分配内存
【发布时间】:2010-04-21 01:16:09
【问题描述】:

我需要从套接字接收 recv() 数据并将其存储到缓冲区中,但我需要确保获取所有数据,以便循环中的内容。因此,为了确保缓冲区中的空间不会用完,我尝试使用 realloc 来调整分配给缓冲区的内存大小。到目前为止,我有:

 // receive response
 int i = 0;
 int amntRecvd = 0;
 char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
 while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
  i += amntRecvd;
  realloc(pageContentBuffer, 4096 + sizeof(pageContentBuffer));
 }

但是,这似乎无法正常工作,因为 Valgrind 抱怨“valgrind:‘不可能’发生了:”。有关如何正确完成此操作的任何建议?

谢谢, 赫里斯托

更新...我意识到我使用 realloc 不正确。这是一个修订版:

 int i = 0;
 int amntRecvd = 0;
 char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
 while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
  i += amntRecvd;
  char *temp = realloc(pageContentBuffer, 4096 + sizeof(pageContentBuffer));
  if (temp != NULL) {
   pageContentBuffer = temp;
  }
 }

然而,valgrind 仍在抱怨:

==25812== Syscall param socketcall.recvfrom(buf) points to unaddressable byte(s)
==25812==    at 0x33B880DAA1: recv (in /lib64/libpthread-2.5.so)
==25812==    by 0x401D78: tunnelURL (proxy.c:371)
==25812==    by 0x40142A: client_thread (proxy.c:194)
==25812==    by 0x33B8806616: start_thread (in /lib64/libpthread-2.5.so)
==25812==    by 0x33B7CD3C2C: clone (in /lib64/libc-2.5.so)
==25812==  Address 0x5642768 is 0 bytes after a block of size 4,104 alloc'd
==25812==    at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==25812==    by 0x401D47: tunnelURL (proxy.c:373)
==25812==    by 0x40142A: client_thread (proxy.c:194)
==25812==    by 0x33B8806616: start_thread (in /lib64/libpthread-2.5.so)
==25812==    by 0x33B7CD3C2C: clone (in /lib64/libc-2.5.so)

【问题讨论】:

    标签: c recv realloc


    【解决方案1】:

    除了@whirlwind 所说的,还有第二个问题:

    sizeof 不返回之前分配的内存量,它实际上是一个编译时构造,相当于sizeof(char *),即字符指针的大小。

    您需要在变量中手动跟踪缓冲区的长度。没有标准的方法来“询问”malloc/realloc 分配了多少内存。

    【讨论】:

    • 是的,sizeof(pageContentBuffer) 和 sizeof (char *) 一样
    【解决方案2】:

    可能存在问题,因为您误用了 realloc()。您需要查看它是否返回一个新指针,如果是,则存储该指针。

    // receive response
    int i = 0;
    int amntRecvd = 0;
    char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
    while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
        i += amntRecvd;
        pageContentBuffer = realloc(pageContentBuffer, 4096 + sizeof(pageContentBuffer));
    }
    

    【讨论】:

      【解决方案3】:

      Look up realloc.

      sizeof 是编译时值,而不是运行时值。

      realloc 有可能返回 0。

      试试这个...

      // receive response
      int i = 0;
      int amntRecvd = 0;
      int currentSize = 4096;
      int oldSize = currentSize;
      char *pageContentBuffer = (char*) malloc(currentSize);
      while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
          i += amntRecvd;
          oldSize = currentSize; 
          currentSize += 4096; 
          char *newBuffer = malloc(currentSize); 
          memcpy(newBuffer,pageContentBuffer,oldSize); 
          free(pageContentBuffer); 
          pageContentBuffer = newBuffer;
      }
      

      最好的办法是重新分配、复制然后显式释放内存——realloc 很古怪。

      【讨论】:

      • 你能给我一个具体的例子吗?“你最好的办法是重新分配,复制然后删除内存”
      • @Hristo int oldSize = currentSize;当前大小 += 4096; char *newBuffer = malloc(currentSize); memcpy(newBuffer,pageContentBuffer,oldSize);空闲(页面内容缓冲区); pageContentBuffer = newBuffer;我还没有验证它,但这是要点
      • 非常感谢罗曼。这似乎解决了我的问题,但是 Valgrind 抱怨“newBuffer”内存正在泄漏。我尝试在几个地方用 free()-ing 修复它,但每个地方都导致了更多问题。有什么建议吗?
      • @Romain。想出了如何释放 newBuffer。在函数返回我创建的新变量后,我必须释放。非常感谢!
      • @Hristo - 我没看到 - 我正在寻找。 - 你确定是 newBuffer 吗?
      【解决方案4】:

      您的主要问题是您重新分配了错误的内存量。你想要的

      realloc(pageContentBuffer, 4096 + i);
      

      sizeof(pageContentBuffer) 只是 sizeof(char *),这意味着您重新分配的空间远远少于第二次读取所需的空间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        • 1970-01-01
        • 2014-11-11
        • 2015-04-15
        • 2012-04-04
        相关资源
        最近更新 更多