【问题标题】:Is it really important to free allocated memory if the program's just about to exit? [duplicate]如果程序即将退出,释放分配的内存真的很重要吗? [复制]
【发布时间】:2016-01-03 03:27:25
【问题描述】:

我了解,如果您分配内存来临时存储某些内容,例如响应用户操作,当代码再次到达该点时,您不再需要内存,您应该释放内存所以它不会导致泄漏。如果不清楚,以下是我知道释放内存很重要的示例:

#include <stdio.h>
#include <stdlib.h>

void countToNumber(int n)
{
    int *numbers = malloc(sizeof(int) * n);

    int i;
    for (i=0; i<n; i++) {
        numbers[i] = i+1;
    }
    for (i=0; i<n; i++) {
        // Yes, simply using "i+1" instead of "numbers[i]" in the printf would make the array unnecessary.
        // But the point of the example is using malloc/free, so pretend it makes sense to use one here.
        printf("%d ", numbers[i]);
    }
    putchar('\n');

    free(numbers); // Freeing is absolutely necessary here; this function could be called any number of times.
}

int main(int argc, char *argv[])
{
    puts("Enter a number to count to that number.");
    puts("Entering zero or a negative number will quit the program.");

    int n;
    while (scanf("%d", &n), n > 0) {
        countToNumber(n);
    }

    return 0;
}

但是,有时,我会在程序运行的整个过程中都需要该内存,即使我最终为同一目的分配了更多内存,存储在先前分配的内存中的数据仍会被使用。所以我最终需要释放内存的唯一一次是在程序退出之前。

但是如果我最终不释放内​​存,那真的会导致内存泄漏吗?我认为操作系统会在进程退出后立即回收内存。即使它不会导致内存泄漏,是否还有其他原因释放内存很重要,前提是这不是 C++ 并且不需要调用析构函数?

例如,下面的例子中是否需要free 调用?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    void *ptr = malloc(1024);
    // do something with ptr
    free(ptr);
    return 0;
}

在那种情况下,free 并不是很不方便,但在我为包含指向 other 动态分配数据的指针的结构动态分配内存的情况下,最好知道我不需要设置循环来做到这一点。特别是如果结构中的指针指向具有相同结构的对象,我需要递归删除它们。

【问题讨论】:

  • 是的,因为你的程序会随着时间的推移而改变,你会忘记这个 hack
  • 正确的资源所有权规则是理解如何构建系统的一部分。您的问题也可能是“如果只是简单的事情,我真的需要了解我在做什么吗”。
  • 主要问题是,在您编写了执行动态分配的代码之后,您应该立即编写清理代码。否则,在清理方式确实很重要的情况下,您最终会编写出内存泄漏的程序。 free() 永远不会造成任何伤害。

标签: c pointers memory-management memory-leaks free


【解决方案1】:

一般来说,操作系统会回收内存,所以不,你没有free()它。但这样做确实是一种很好的做法,在某些情况下,它实际上可能会有所作为。几个例子:

  • 您将程序作为另一个进程的子进程执行。根据完成的方式(参见下面的 cmets),在父级完成之前不会释放内存。如果父母永远不会完成,那就是永久泄漏。
  • 您更改程序以执行其他操作。现在你需要寻找每一条出口路径并释放一切,你可能会忘记一些。
  • 回收内存是操作系统的意愿。所有主要的都这样做,但如果您将程序移植到另一个系统,它可能不会。
  • 静态分析和调试工具使用正确的代码可以更好地工作。
  • 如果内存是在进程之间共享的,则只能在所有进程终止后释放它,或者甚至可能不会释放。

顺便说一句,这只是关于记忆。释放其他资源,例如关闭文件 (fclose()) 更为重要,因为某些操作系统 (Windows) 无法正确刷新流。

【讨论】:

  • 很好,但对于最后一个声明:释放其他资源,例如关闭文件 (fclose()) 更为重要。,所有打开的文件都在程序之前关闭终止
  • @AlterMann 是的,但是写入它的任何数据都不会被刷新。尝试打开一个文件进行写入,向其中写入几个字节,然后在不关闭的情况下退出(或fflush())。你最终会得到一个空文件。
  • @mitjanic: nops, (C99, 7.19.3p5) "如果主函数返回到它的原始调用者,或者如果调用了退出函数,所有打开的文件都被关闭(因此所有输出流都是刷新)在程序终止之前。”
  • @AlterMann 好吧,我会的。我仍然坚持我原来的观点,因为至少 Windows/MSVC 不遵循标准,这是一个非常重要的平台。不过,你是完全正确的。谢谢!
  • @AlterMann - 如果在刷新这些输出流时出现错误?刷新流与任何其他写入操作相同 - 它可能会失败。在exit() 上刷新流或从main() 返回提供没有错误检查
猜你喜欢
  • 2010-09-25
  • 2018-08-29
  • 2018-07-27
  • 2011-08-02
  • 2010-11-02
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多