【问题标题】:When is it "allowed" not to free dynamically allocated memory?什么时候“允许”不释放动态分配的内存?
【发布时间】:2020-02-11 19:48:37
【问题描述】:

我知道,任何动态分配的内存都必须在使用结束时释放,free()。 但是,我确实有一个提供以下功能的库:

char *rsprintf_s(const char *format, ...);

它与asprintf 做同样的事情,但直接返回在该函数中动态生成的字符串。例如:

int main()
{
    char *my_str = rsprintf_s("A number: %d, a string: %s.", 42, "StackOverflow");
    printf("`rsprintf_s` result: '%s'", my_str);
    return 0;
}

这会产生以下结果:`rsprintf_s` 结果:'一个数字:42,一个字符串:“StackOverflow”'

我想这个程序中存在内存泄漏,这将迫使我这样做:

int main()
{
    char *my_str = rsprintf_s("A number: %d, a string: %s.", 42, "StackOverflow");
    printf("`rsprintf_s` result: '%s'", my_str);
    free(my_str);
    return 0;
}

但是,它是惯用的功能吗?如果存在,那么在这种情况下不释放内存是否被认为是一个小问题?我想知道这样的功能是否可以不用担心每次都释放内存,虽然我对此表示怀疑。

【问题讨论】:

  • “如果存在,那么不释放是不是小问题” 为什么这个函数存在意味着内存泄漏是一个“小问题”?
  • 调用者有责任在使用完内存后free。您有责任记录您的函数分配内存并且调用者拥有该内存的事实(即必须free 它)。有关示例,请参见 strdup 的手册页。
  • rsprintf_s 定义在哪里?

标签: c free


【解决方案1】:

如果您有一个要快速退出的小程序,并且您在功能齐全的现代桌面或服务器操作系统上运行,那么您可能可以依靠操作系统在进程终止时清理分配的堆内存;见here

除非 rsprintf_s 明确告诉您应该释放它返回的内容,否则我不会认为是这种情况。它可能有一个甚至不使用堆内存的实现(也许它使用静态分配的全局内存,也许在 DATA 部分或其他地方)。

【讨论】:

    【解决方案2】:

    我知道,任何动态分配的内存都必须在使用结束时释放,free()

    没有。不释放会导致程序为其他目的分配的内存更少。它可能(也可能不会)导致程序的内存占用比其他情况下更大。在公然、扩展或极端的情况下(根据环境相关的方式判断),这可能意味着(虚拟)内存不足,无法为其他应用程序提供服务,或为泄漏的应用程序提供服务。但这些都不意味着您必须释放内存。你总是可以选择接受不这样做的后果。

    在大多数情况下,肆意无视释放分配的内存的次要优势无法平衡对程序和运行它的系统的负面影响,但在某些情况下它不会导致任何实际问题.今天使用的所有主要操作系统都会在进程终止时释放进程分配的内存。因此,在您可能遇到的大多数系统上,短期运行程序中的小泄漏是相当无关紧要的,并且是否应该在程序终止之前释放需要使用的内存是一种风格问题,而不是实用性问题。

    这将我们直接带到您的示例程序。

    但是,它是惯用的功能吗?如果存在,那么在这种情况下不释放内存是否被认为是一个小问题?

    我认为您的意思是“如果它退出”。如上所述,一方面在退出对main() 的顶级调用之前手动释放与将其留给操作系统进行清理,对程序或系统的实际影响基本上没有区别。

    我想知道这样的功能是否可以不用担心每次都释放内存,虽然我对此表示怀疑。

    如果您忽略释放分配的内存而不仔细考虑这样做是否会产生问题,您将面临给自己和他人带来麻烦的严重危险。在某些情况下,您可能会不解脱,但可以这么说,不担心就这样做是愚蠢的。此外,就您的经验水平而言,您可能还没有能力在这方面做出良好的判断。

    我实际上会反过来说:确保在不再需要时释放分配的内存是无忧的选择。或者至少不用担心。通过培养支持它的编程实践,您可以相对容易地做到这一点。

    【讨论】:

      【解决方案3】:

      如果您在操作系统上,行为不端的进程实际上不会造成太大的被动伤害,那么实际上它是可以的。破坏文件等主动危害是另一回事,但在程序退出时未释放内存不会与这些系统 API 交互。因此,当程序在这样的操作系统(例如任何现代桌面操作系统)中运行时,从某种意义上说,在程序退出时忽略空闲内存总是好的。

      从不同的角度来看,它永远不会很好。原因包括,从我的头顶上看:

      • 当您出于某种原因必须时,故意编写不可移植的代码并不是很聪明。你永远不知道未来会发生什么。
      • 对记忆马虎,对其他事情不马虎,这是一种很难维持的心态。只是不要对您的代码草率。
      • 现在的程序退出可能最终只是错误处理功能并稍后恢复正常运行,然后首先很容易忘记修复内存泄漏,并且您可能需要进行大量重构,当您突然需要访问要在之前已将其丢弃的位置释放的指针。
      • 当他们看到泄漏时,其他程序员会认为整个程序以及编写程序的程序员的扩展都不好。
      • 在其他语言(例如 C++)中,释放内存与调用清理代码(如类析构函数)相结合,而这些代码反过来可能会刷新缓冲区和关闭文件,不这样做会留下损坏的文件等。最好不要开发使用 C 的坏习惯,你需要用不同的语言改掉。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-12
        • 2011-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多