动态分配的内存什么情况下可以不释放?

3
我知道,任何动态分配的内存必须在使用结束时使用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;
}

然而,这是一个惯用函数吗?如果存在,那么在这种情况下不释放内存是否被视为小问题?我想知道是否可以使用这样的函数,而无需每次都担心释放内存,尽管我有所怀疑。


如果它存在,那么不释放内存是否被认为是一个小问题?为什么这个函数的存在意味着内存泄漏只是一个“小问题”? - HolyBlackCat
当调用者完成使用内存后,释放内存是调用者的责任。你有责任记录函数分配内存的事实,并且调用者拥有该内存(即必须free它)。例如,请参阅strdup的手册页面。 - user3386109
rsprintf_s 定义在哪里? - Fiddling Bits
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
4

如果您有一个将很快退出的小程序,并且正在运行全功能现代桌面或服务器操作系统,则可能可以依赖操作系统在进程终止时清理已分配的堆内存;请参见这里

除非rsprintf_s明确告诉您应该释放它返回的内容,否则我不会假设这是情况。它可能具有不使用堆内存的实现(也许它使用静态分配的全局内存,也许在数据段或类似区域中),请注意。


3
我知道,任何动态分配的内存在使用结束后必须使用free()进行释放。 但不进行释放会导致程序可分配给其他用途的内存减少。它可能(也可能不)导致程序的内存占用比本来应该占用的更大。在某些情况下,这可能意味着无法为其他应用程序提供足够(虚拟)内存,甚至无法为泄漏自身的程序提供服务。但是这些事情并不意味着您必须释放内存。您始终可以选择接受不这样做的后果。 尽管不释放分配的内存带来的微小优势往往无法抵消其对程序和运行系统的负面影响,但有些情况下不会造成任何实际问题。今天所有主要操作系统都会在进程终止时释放进程的分配内存。因此,在大多数您可能遇到的系统上,短时间运行的程序中的小泄漏相当无关紧要,而是否应该释放一直需要使用到程序终止前的内存则是一个风格问题,而非实用性问题。 这就直接涉及到您的示例程序。 然而,这种函数是否属于惯用方式?如果这个函数存在,那么在这种情况下,不释放内存是否被认为是一个小问题? 正如上面讨论的那样,在手动释放顶层main() 调用退出前一刻与让操作系统清理之间,实际上对程序或系统影响差别不大。 我认为您是想说"如果它存在"。如果您忽略释放分配的内存而没有仔细考虑这样做是否会产生问题,那么您将可能给自己和其他人带来麻烦。在某些情况下,您可以不释放而运行程序,但这样做是愚蠢的,毕竟您显然还没有足够的经验在这个领域做出正确的判断。事实上,确保在不再需要时释放分配的内存是无忧无虑的选择。或者至少减少了担忧。通过培养支持此方式的编程实践,您可以使其相对容易实现。

1
如果您使用的操作系统不会受到失控进程带来的被动危害,那么实际上没有问题。例如破坏文件等主动危害是另一回事,但在程序退出时未释放内存将不会与这些系统API交互。因此,在这样的操作系统中运行程序时,省略程序退出时的内存释放,在某种意义上总是可以的(例如任何现代桌面操作系统)。 从不同的角度来看,永远都不可以。我能想到的原因包括:
  • 如果没有必要,故意编写不可移植的代码是不明智的。你永远不知道未来会发生什么。
  • 在不粗心处理其他事情的同时,对内存粗心大意,这是一种难以维护的心态。不要对你的代码粗心大意。
  • 现在程序退出可能最终只是错误处理函数,并在稍后恢复正常操作,首先很容易忘记修复内存泄漏,进一步地,当你突然需要访问要释放的指针时,你可能需要做大量的重构,而之前你已经将其丢弃了。
  • 当其他程序员看到内存泄漏时,他们会对整个程序和编写它的程序员产生负面看法。
  • 在其他语言中,例如C++,释放内存与调用清理代码(如类析构函数)耦合,而这些清理代码可能会刷新缓冲区和关闭文件,不这样做可能会留下损坏的文件等问题。最好不要在C中养成不良习惯,否则你需要在学习不同的语言时取消这些习惯。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,