【问题标题】:Memory leak with strings?字符串内存泄漏?
【发布时间】:2014-04-30 04:07:18
【问题描述】:

我是 C 新手,所以这可能很明显,但我仍然不确定。 Java 帮我解决了这个问题^^

我有一个替换表、输入字符串和一个函数str_replace,它对字符串做了一些工作。 str_replace 内部调用 malloc 为新字符串获取空间(它返回一个新分配的 char*。

char* color_tags(char* s) {

    char* out = s;

    // in real, the table is much longer
    static char* table[4][2] = {
        {"<b>", BOLD},
        {"<u>", UNDERLINE},         
        {"</b>", BOLD_R},
        {"</u>", UNDERLINE_R},
    };


    for(int r=0; r<4; r++) {
        // here's what bothers me
        out = str_replace(table[r][0], table[r][1], out);
    }

    return out;
}

如您所见,char* out 被指向新字符串的指针所取代,因此旧字符串显然最终会导致内存泄漏——如果我完全理解错误的话。

有什么更好的方法呢?

【问题讨论】:

  • 呃……你还有 s 飘来飘去。只要不在别处修改,以后就可以free(s);了。
  • str_replace 是否释放旧字符串?
  • 不,它没有。为了完整起见,这里是我得到 str_replace 的地方:binarytides.com/str_replace-for-c
  • 哦,不。这是缺乏理解的复制/粘贴。
  • 我自己编写了这段代码,它只是我从其他来源获得的 str_replace。我的弦乐还不是很好。无论如何,您可以看到它的作用。

标签: c memory malloc memory-leaks


【解决方案1】:

[这更像是一个评论而不是一个答案——abacabadabacaba 已经发布了答案——但我希望它能澄清一些事情。]

我会争辩说内存泄漏就在这句话中:

str_replace 内部调用 malloc 为新字符串获取空间 […]

[emphasis mine] 内存管理是 C 中的一个基本问题,如果一个函数分配的内存它自己没有取消分配,那么这是该函数的一个主要属性,需要记录下来-front,以及有关调用者应该如何处理的信息。它不应该被认为是函数的“内部”,并且你不应该阅读整个函数的源代码来确定它。这足以让我对函数的其余部分产生怀疑(事实上,快速浏览一下该函数就足以注意到很多问题:它的参数类型应该是 const char * 而不是 char *;它应该检查malloc 的返回值;可以通过跟踪 new_subject 的尾部来提高效率,或者使用 strcat 进行更清洁,而不是当前最坏的两个世界;等等)。

你最初没有写str_replace,但是你可以修改你自己的版本,所以你应该从这里改变它的文档:

在一个字符串中搜索并用另一个字符串替换一个字符串

到这样的事情:

创建并返回subject 的副本,但所有出现的子字符串search 都替换为replace。返回的字符串是使用malloc新分配的;调用者应使用free

(您的color_tags 函数将需要类似的文档,因为它也使用malloc 返回一个新分配的字符串。)

在手头的文档中,有一个明确的“所有权”链:str_replace 的调用者拥有它返回的字符串的所有权。所以color_tags 必须为str_replace 返回的每个字符串调用free除了color_tags 本身将返回的字符串(这又将由@ 的调用者“拥有” 987654341@)。因此 abacabadabacaba 的答案。

【讨论】:

    【解决方案2】:

    代码总共泄漏了 3 个字符串:除了最后一个之外,每次迭代之后都有一个。解决方案是在使用后释放每个字符串。代码可能如下所示:

    for(int r=0; r<4; r++) {
        char* new_out = str_replace(table[r][0], table[r][1], out);
        if (r>0) {
            // out is an intermediate value which will never be used again, free it
            free(out);
        }
        out = new_out;
    }
    

    【讨论】:

    • 实际上在这样做之后,我得到了一个奇怪的内存违规错误,一切都崩溃了。不知道发生了什么。
    • 这可能是因为其他地方的错误。在像 C 这样的不安全语言中,错误可能只有在一些不相关的更改之后才开始显现。您可以尝试使用 Valgrind 之类的程序来查找问题的根源。
    • 你是对的,问题出在 str_replace,它会导致难以置信的内存泄漏。
    • -1,您将尝试释放最初分配给表条目的字符串文字。
    • @JensGustedt:这不是真的。
    猜你喜欢
    • 2011-08-29
    • 2013-04-03
    • 2011-06-12
    • 2018-12-17
    • 2013-12-03
    • 2011-05-04
    • 2011-08-29
    • 2021-01-26
    • 1970-01-01
    相关资源
    最近更新 更多