【问题标题】:realloc() leaking memoryrealloc() 内存泄漏
【发布时间】:2011-05-31 16:59:31
【问题描述】:

我有一个向字符串添加字符的函数:

void AddChToString(char **str,char ch){
    int len=(*str)?strlen(*str):0;
    (*str)=realloc(*str, len+2);
    (*str)[len]=ch;
    (*str)[len+1]='\0';
}

Instruments(在 Mac 上)和 Valgrind 指示以下行: (*str)=realloc(*str, len+2) 正在泄漏内存。这是 realloc 的实现问题吗?还是我使用不当?

这是 Valgrind 的输出:

==39230== 6 bytes in 1 blocks are definitely lost in loss record 1 of 7
==39230==    at 0x100018B2D: realloc (vg_replace_malloc.c:525)
==39230==    by 0x100002259: AddChToString (in ./OpenOtter)
==39230==    by 0x10000477B: QueryMapFromString (in ./OpenOtter)
==39230==    by 0x100684CD2: ???
==39230==    by 0x100001FB0: RequestHandler (in ./OpenOtter)
==39230==    by 0x100065535: _pthread_start (in /usr/lib/libSystem.B.dylib)
==39230==    by 0x1000653E8: thread_start (in /usr/lib/libSystem.B.dylib)
==39230== 
==39230== 9 bytes in 1 blocks are definitely lost in loss record 2 of 7
==39230==    at 0x100018B2D: realloc (vg_replace_malloc.c:525)
==39230==    by 0x100002259: AddChToString (in ./OpenOtter)
==39230==    by 0x10000298E: ParseHTTPRequest (in ./OpenOtter)
==39230==    by 0x100004151: OpenRoutesFile (in ./OpenOtter)
==39230==    by 0x10000142B: main (in ./OpenOtter)
==39230== 
==39230== 45 bytes in 5 blocks are definitely lost in loss record 3 of 7
==39230==    at 0x100018B2D: realloc (vg_replace_malloc.c:525)
==39230==    by 0x100002259: AddChToString (in ./OpenOtter)
==39230==    by 0x10000298E: ParseHTTPRequest (in ./OpenOtter)
==39230==    by 0x100001EB4: RequestHandler (in ./OpenOtter)
==39230==    by 0x100065535: _pthread_start (in /usr/lib/libSystem.B.dylib)
==39230==    by 0x1000653E8: thread_start (in /usr/lib/libSystem.B.dylib)
==39230== 
==39230== LEAK SUMMARY:
==39230==    definitely lost: 60 bytes in 7 blocks
==39230==    indirectly lost: 0 bytes in 0 blocks
==39230==      possibly lost: 0 bytes in 0 blocks
==39230==    still reachable: 1,440 bytes in 4 blocks
==39230==         suppressed: 0 bytes in 0 blocks

谢谢。

【问题讨论】:

  • 如果您不使用第一个间接寻址,为什么还要使用指向指针的指针?
  • 您使用的是什么仪器?如果您使用的只是显示虚拟内存大小的东西,那么它不是问题(好吧,至少不是realloc() 的问题...另一方面,该代码)
  • 如果 realloc() 返回 NULL,你会丢失指向内存的指针。
  • @delnan: realloc 可能会返回与您传递给它的地址不同的地址。如果不使用双重间接,函数调用者将无法获得新地址。
  • "这是 realloc 的实现问题吗?" “我是否使用不当?” 是的

标签: c string memory-leaks


【解决方案1】:

您的仪器是否表明存在实际泄漏或存在潜在泄漏?

像你这样使用realloc() 会泄漏内存如果 realloc() 失败。在这种情况下,它将返回NULL,但不会释放原始块。因此,您将丢失指向块的指针并且无法释放它(除非指针存储在其他位置)。

但这应该很少发生(即,当您耗尽内存时)。

如果这是您的工具所抱怨的问题,您应该能够通过以下方式修复泄漏警告:

void AddChToString(char **str,char ch){
    int len=(*str)?strlen(*str):0;
    char* tmp = realloc(*str, len+2);

    if (!tmp) {
        // whatever error handling is appropriate
    }

    (*str)=tmp;
    (*str)[len]=ch;
    (*str)[len+1]='\0';
}

【讨论】:

  • valgrind 这样的运行时泄漏检查器,据我所知,不做这种检查。
  • @peoro - 写答案时,没有关于使用的工具、它们的输出或它们在哪里运行时检测或静态检查工具(lint 或类似工具)的具体信息。
  • 甚至 55 分钟前发布的原始消息都在谈论 Valgrind。无论如何,我并不是说你错了或其他什么,只是添加一点(也许是迂腐的?)观察。
【解决方案2】:

调用 realloc 本身不会泄漏内存。您应该确保重新分配的字符串的内存在不再需要后被释放。

【讨论】:

  • 原来调试器告诉我内存分配在哪里,而不是在哪里泄漏。
  • @Maz:如果您从不释放块,它的分配位置就是泄漏的位置(至少这是工具可以识别它的唯一方法)。所以你是说传递给AddChToString() 的指针从未在其他地方释放,对吧?
  • 是的,我就是这么说的。我对内存调试器没有太多经验,我认为这些信息解释了对内存的最后一次已知引用超出范围的位置,而不是分配内存的位置。
【解决方案3】:

我不知道关于realloc 的实现问题,但是这段代码中肯定存在内存泄漏的机会:来自realloc 手册页:

如果 realloc() 失败,则原始块保持不变;它没有被释放或移动。

而且,由于realloc 在失败时返回NULL,如果失败,您将丢失指向已分配内存块的唯一指针,因此您有内存泄漏。

为了避免这个问题,你应该这样做:

char * temp=realloc(*str, len+2);
if(temp==NULL)
{
    /* handle the error in some way */
}
else
    *str=temp;

【讨论】:

    【解决方案4】:

    尝试使用单独的变量重新分配,然后调用 strcpy 将 str 变量放入该空间,如下所示:

    void AddChToString(char **str,char ch){
    char *blah;
    int len=(*str)?strlen(*str):0;
    blah=realloc(NULL, len+2);
    strcpy(blah, str); 
    (*str)[len]=ch;   
    (*str)[len+1]='\0'; } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      • 1970-01-01
      • 2020-09-19
      • 2015-02-19
      • 2018-03-23
      • 2020-11-09
      • 1970-01-01
      相关资源
      最近更新 更多