【问题标题】:strdup() causing memory leaks?strdup() 导致内存泄漏?
【发布时间】:2016-01-18 09:51:29
【问题描述】:

我已经实现了一个返回字符串的函数。它接受一个整数作为参数(age),并返回一个格式化字符串。

一切都运行良好,除了我有一些疯狂的内存泄漏。我知道 strdup() 是造成这种情况的原因,但我试图研究一些修复无济于事。

我的代码是:

const char * returnName(int age) {

    char string[30];

    sprintf( string, "You are %d years old", age);

    return strdup(string);
}

Valgrind 的输出是:

==15414== LEAK SUMMARY:
==15414==    definitely lost: 6,192 bytes in 516 blocks
==15414==    indirectly lost: 0 bytes in 0 blocks
==15414==      possibly lost: 0 bytes in 0 blocks
==15414==    still reachable: 0 bytes in 0 blocks
==15414==         suppressed: 0 bytes in 0 blocks

非常感谢您在解决此内存泄漏问题方面的任何帮助。

【问题讨论】:

  • 你已经展示了分配的代码,释放的代码在哪里?
  • 你读过strdup的任何文档吗?
  • 代码是否最终free()returnName() 返回的指针?如果没有,则有泄漏。
  • 你需要free strdup 的结果在某些时候,这反过来意味着你需要将返回类型更改为只是(非constchar *
  • 我如何在该变量所在的函数之外释放一个局部变量?回答这个问题 - 由于上述担忧,我没有释放 strdup。

标签: c memory-leaks strdup


【解决方案1】:

strdup() 本质上等价于

char* dup = malloc(strlen(original) + 1);
strcpy(dup, original);

所以你需要记住在使用完字符串后调用free()

const char* name = returnName(20);
/* do stuff with name */
free((void*)name);

如果你不打电话给free(),那么 valgrind 当然会报告泄漏。

【讨论】:

  • 在下面向另一个用户询问了这个问题:如果我在这样的主要方法中打印怎么办:printf("%s", returnName(3)); 所以在调用该方法时没有关联的变量名称,例如name - 如何我免费吗?谢谢。
  • @user2832891 然后,你造成了内存泄漏。您需要将一个变量与其关联,以便您以后可以free它。
  • @PCLuddite 你刚刚复制了我的答案吗?
  • @Michi 我没有尝试过,但我知道你会怎么想。我将示例更改为较早的编辑,以便有一些变化。
  • @Michi 本着公平竞争的精神,我赞成你的回答。对于任何侵权行为,我深表歉意。
【解决方案2】:

来自man strdup

新字符串的内存是通过以下方式获得的 malloc(3),可以用free(3)释放。

所以你需要freestrdup分配和返回的空间。

假设你像这样调用returnName

 const char* str = returnName(3);

完成str 后,您可以像这样free

free((char*) str);

需要转换,因为free 需要一个非常量 void*。这种显式转换在这里没问题,因为returnName 实际上应该返回常量数据1。在这里调用free 只是一个讨厌的实现细节。


1 正如在 cmets 中与 @M.M 讨论的那样。

【讨论】:

  • 如果我在这样的主方法中打印怎么办:printf("%s", returnName(3)); 所以在调用该方法时没有关联变量名称,例如str - 我将如何释放它?
  • const char* str = returnName(3); printf("%s\n", str);
  • 希望我可以避免显式声明一个新变量,但我想这是必须的。谢谢。
  • 在完全尝试输入的内容时出现以下错误:note: expected ‘void *’ but argument is of type ‘const char *’ extern void free (void *__ptr) __THROW;
  • 函数仍然可以返回const char *。可以释放 const 指针。您可能意味着无法释放指向 const 的指针,但是您可以在调用 free 之前将指针转换为 void *(或 char *)。
【解决方案3】:

strdup 看起来像这样:

char *strdup(const char *str){
    size_t n = strlen(str) + 1;
    char *dup = malloc(n);

    if(dup){
        strcpy(dup, str);
    }

    return dup;
}

如您所见,malloc 也参与其中,这意味着在您使用 strdup 动态分配该内存之后的某个时间点,您必须在不再需要它之后再使用free

【讨论】:

    【解决方案4】:

    内存泄漏的原因不是对 strdup() 的调用,而是因为 post 函数的调用者在处理完字符串后未能将返回的指针传递给 free()。

    【讨论】:

      【解决方案5】:
      const char * returnName(int age) {
          char string[30];
          sprintf( string, "You are %d years old", age);
          return strdup(string);
      }
      

      returnName() 的返回类型是 const char*。因此,您不能将返回值保存到 char* 类型变量中。将返回值保存到 const char* 变量和 cast 它到 char* 同时内存 free

      const char* retName = returnName(3);
      // Use retName
      free((char*)retName);
      

      【讨论】:

        猜你喜欢
        • 2016-06-04
        • 2012-08-14
        • 1970-01-01
        • 2015-07-06
        • 2014-06-07
        • 2013-11-20
        • 2011-10-28
        • 2012-12-13
        • 1970-01-01
        相关资源
        最近更新 更多