【问题标题】:How to free memory of temporary string?如何释放临时字符串的内存?
【发布时间】:2011-11-27 16:42:04
【问题描述】:

我正在使用我的自定义字符串库,顺便说一句,这很糟糕,但我这样做是为了经验。

无论如何,我有一些函数可以为String* 分配一块内存以供使用,并且工作正常。当调用string_delete(string*) 函数时,所有使用的内存都会被释放。 但是我想出了一种将char*s 表示为String*s 的新方法,但我担心我为它保留的内存不会被释放。这是函数:

String* String_ToN(char* dest) {
  String* temp = calloc(1, sizeof (struct String));
  temp->length = strlen(dest);
  temp->buffer = (char*) malloc(temp->length + 1);
  strncpy(temp->buffer, dest, temp->length);
  return temp;
}

我不喜欢使用strdup,因为它不是标准c,所以我会坚持使用mallocstrncpy

这行得通,我用它的目的是这样的:

String_GetLength(String*) 接受一个String* 参数,所以如果我在调用它时输入一个字符串文字,我会得到一个错误。

所以我改为使用String_GetLength(String_ToN("hello")),它会返回 5,就像我预期的那样。

但再次在String_ToN 中我使用callocmalloc,我将如何释放这些内存并仍然能够使用ToN

【问题讨论】:

    标签: c string memory-leaks struct memory-management


    【解决方案1】:

    与 C++ 不同,C 中没有自动资源管理(因为没有析构函数)。您必须执行以下操作:

    String *hello = String_ToN("hello");
    int len = String_GetLength(hello);
    String_free(hello);
    

    String_free 进行所有必要的清理工作。

    【讨论】:

    • 无论如何我可以将 char* 传递给 String* 参数,而无需编写重复的函数,而是使用 char* 而不是 String*?
    • @sikes:如果涉及到资源的动态分配,那就没有。
    • @sikesusmc 并非没有对 String 的结构进行一些高级摆弄,使其看起来像一个 char[]。但是您只能在不需要其余字符串成员的地方使用 char* 函数,因此您可以将函数编写为 char* 函数,即 Chars_GetLength(char*),并通过调用这些函数来实现您的 String 函数,即 String_GetLength(String *s){ return Chars_GetLength(s->buffer); }
    【解决方案2】:

    你可能需要一个函数来删除或释放你的String-s,也许

    void String_delete(String *s) {
      if (!s) return;
      free (s->buffer);
      // you might want memset(s, 0, sizeof(*s)); to catch more bugs
      free (s);
    }
    

    您可能希望在free-ing 之前将内存归零(如注释代码中所示)。它可能有助于捕获悬空指针错误。但是你可以使用像valgrind 这样的工具来捕捉它们。或者,使用Boehm's garbage collector 非常有用:您可以使用GC_malloc 代替malloc (等等...),并且不要打扰调用freeGC_free。您会根据经验发现,释放内存成为大型编程项目中的一个主要问题(不,RAII idiom 不是灵丹妙药)。

    【讨论】:

    • 当您在下一行释放s 时,s->length = 0point 是什么?
    • 它实际上可以帮助捕获一些悬空指针错误......但我同意原则上它是无用的......
    【解决方案3】:

    正如 Oli Charlesworth 所指出的,您必须创建临时对象。但是,您也可以添加一个标志

    int dispose;
    

    到您的 String 结构,然后在传递给某个函数时设置它。然后每个获取您的字符串的函数都必须检查此标志,如果设置,则释放字符串结构。代码可能如下所示:

    Process_String(String_ToN("Hello", 1));
    

    然后

    Process_String(String *str) {
        /* do smth with str */
        if(str->dispose)
            String_Delete(srt);
    }
    

    我同意这种设计更容易出错,而不是正常完成工作的方式。因此,将其视为教育示例,不多也不少。

    【讨论】:

    • 可以这样做,但不建议这样做。很容易出错,把清理的责任放在了错误的地方。
    • 但我没有创建在字符串源之外可见的新对象,因为 String_ToN 是在函数内创建的。 free(String_ToN) 会起作用吗?
    • @sikes usmc:是的,它会起作用的。您传递的是指向新分配对象的指针。然而,这种设计不是标准的,不应作为教育示例用于其他一切。使用 Oli Charlesworth 建议的临时对象。
    猜你喜欢
    • 2011-10-28
    • 2016-06-22
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2019-01-13
    相关资源
    最近更新 更多