【问题标题】:How to deal with pointers to dynamic memory being returned in C/C++如何处理在 C/C++ 中返回的指向动态内存的指针
【发布时间】:2012-10-24 15:45:48
【问题描述】:

我想知道用 C 和 C++ 中返回的指向动态内存的指针来处理内存泄漏的协议。例如,strtok 返回一个 char*。据推测,返回的指针最终必须被释放/删除。我注意到reference page 甚至没有提到这一点。那是因为这只是假设吗?另外,你怎么知道是删除还是释放?是否必须进行研究以找出每个函数最初使用的语言,然后假设所有 C 程序都使用 malloc/free 而 C++ 使用 new/delete?

【问题讨论】:

  • 参考页没有提到它的原因是它不是真的。
  • 我认为重要的是要注意“参考页面”只是a参考页面,而不是功能的标准定义。但在这种情况下,它是正确的。

标签: c++ c memory-management return


【解决方案1】:

strtok 函数不执行任何内存分配。它正在对您提供的字符串指针执行操作。在调用该函数时,您应该已经决定是为堆上的指针分配内存还是使用自动堆栈存储。你可以这样写:

char * p = "Testing - string";
char * p2 = strtok(p, "- ");

这里 p2 不必被释放/删除,因为它是在堆栈上分配的。但是这里

char * p = "Testing - stringh";
char * p2 = malloc(strlen(p));
p2 = strtok(p, "- ");

你已经在堆上为 p2 分配了存储空间,所以在你完成它之后它必须被释放并设置为 null:

if(p2 != NULL) { 
     free(p2);
     p2 = NULL;
}

因此,如果您使用 new 进行堆分配,则使用 delete;如果你使用 malloc/calloc,你应该免费使用。

【讨论】:

  • 您知道,您的回答提出了一个有趣的问题。从技术上讲,您正在玩​​弄程序代码中的字符串。 (因为没有以任何方式分配'p')。通常,这些是“const char”,这意味着它们不能更改。我也相信,如果你在那个函数上调用 strtok,你很可能会让你的程序因分段错误或其他原因而崩溃。您的第二个示例将给您留下内存泄漏(因为您正在覆盖指向已分配内存的指针),最后一个示例将崩溃,因为没有为“p”分配内存。
  • 抱歉,我确实是想释放 p2。释放未分配堆的 p 会导致未定义的行为。谢谢你指出我的错误。
【解决方案2】:

strtok 是一个 C 函数,它返回一个指向先前分配的内存的指针; strtok 本身不分配新内存。

如果分配了malloc 的东西,则必须使用free 释放它;用 new 分配的任何东西都必须是 freed 和 delete

在现代 C++ 中处理内存分配/释放的最佳方法是使用智能指针。看看std::shared_ptr/std::unique_ptr,除非万不得已,否则不要使用原始指针。

同时使用std::stringstd::vector 将删除大部分原始指针。

【讨论】:

    【解决方案3】:

    strtok 不返回指向新分配内存的指针,而是返回指向先前分配的内存位置的指针。

    让我们假设:

    char String[1024];
    strcpy(String, "This is a string");
    char *Ptr = strtok(String, " ");
    

    Ptr 不会指向新分配的内存位置,而是指向 String 的位置(如果我的计数现在没有让我失败的话),空间将被替换为 '\0'。 (

    来自参考: 函数自动用空字符替换标记的结尾,函数返回标记的开头。

    这也意味着,如果您在 strtok 完成工作后再次打印出 'String',它将只包含 'This',因为该字符串在此之后终止。

    根据经验,您可以肯定地说,您只需要释放/删除您自己明确分配的内存。

    这意味着:

    为每个“新”放置一个“删除”,为每个“malloc”放置一个“免费”,这样就很好了。

    【讨论】:

    • 为了扩展这个,库函数需要你释放内存,他们会在他们的文档中告诉你,它们是C还是C++函数是delete还是free的关键是必需的。
    • @LightnessRacesinOrbit 是的,你当然是对的。如果明确说明,释放相关内存当然是必要的。虽然通常这不是用 delete/free 完成的,而是一个专门的“free”函数,它与“construction call”相匹配。
    • 是的,情况也是如此,当然在标准 C 库以外的库中。
    • 没错,例如在WINAPI FormatMessageFORMAT_MESSAGE_ALLOCATE_BUFFER 一起使用时,他们指定您必须使用LocalFree 释放内存。
    猜你喜欢
    • 2015-05-19
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多