【问题标题】:Correct use of free() when deallocating a 2d matrix in c在 c 中释放 2d 矩阵时正确使用 free()
【发布时间】:2018-12-06 21:02:57
【问题描述】:

我刚开始学习 c 编码,我有几个关于二维矩阵和 free() 命令的问题。

我知道你首先需要创建一个带有指针的数组,指向矩阵的不同列:

double **array = (double **)malloc(5*sizeof(double *));
for(int n = 0; n<5; n++){

array[n] = (double *) malloc(6*sizeof(double));

我知道释放此矩阵的正确方法是首先释放各个行,然后释放数组指针本身。大致如下:

for (i = 0; i < nX; i++){  
   free(array[i]); }     

free(array);

我的问题是:为什么这是必要的?我知道这是不正确的,但你为什么不能只使用:free(array)?据我了解,这将释放指针数组。当其他东西需要访问它时,列使用的内存不会被覆盖吗? free(array) 会以任何方式导致内存损坏吗?

非常感谢任何帮助!

【问题讨论】:

  • 它不是二维数组。它是一个包含指向其他数组的指针的数组。所有这些其他数组都存在于内存中的其他位置,需要释放。
  • @ChristianGibbons:它是指向指针的指针,而不是指向数组的指针。
  • @toohonestforthissite 我想保持清楚,这些不是单一的对象。很难以技术上正确但仍然清晰的方式来描述。
  • 不释放行不会导致内存损坏,它只是意味着在程序的生命周期内永远不能再次使用内存(因为它已经被分配并且没有被释放,但你没有知道它在哪里)。如果你这样做太多,你会耗尽内存。

标签: c arrays memory-management malloc free


【解决方案1】:

您的代码不仅为指针数组(蓝色数组)分配内存,而且在 for 循环中,您还为红色数组分配内存。因此,单独的free(array) 行只会释放蓝色数组分配的内存,而不是红色数组。您需要在与他们失去联系之前释放红色的人;也就是说,在释放蓝色数组之前。

顺便说一句;

当其他东西需要访问时,列使用的内存不会被覆盖吗?

没有。操作系统将跟踪您的进程(程序)分配的内存,并且在您的进程终止之前不允许任何其他进程访问分配的内存。在正常情况下——我的意思是,记住 C 语言没有垃圾收集器——操作系统永远不会知道你已经失去了与分配的内存空间的连接,也永远不会尝试像,“嗯,这个内存空间对这个进程没有用不再;所以,让我们重新分配它并为另一个进程服务。”

【讨论】:

    【解决方案2】:

    不会导致损坏,不会,但会造成内存泄漏

    如果在你的程序中完成一次,它可能并不重要(许多专业/昂贵的应用程序都有 - 小的、无意的 - 内存泄漏),但在循环中重复此操作,之后您可能会耗尽内存一会儿。如果您的代码是从外部程序调用的(如果您的代码在库中),情况也是如此。

    另外:不释放缓冲区可能是一种有用的方法(暂时),可以检查您在程序中遇到的崩溃是否源于损坏的内存分配或释放(当您无法使用 Valgrind 时)。但最终你想释放一切,一次

    如果你只想执行一个malloc,你也可以分配一大块,然后计算行的地址。最后,只需释放大块(此处示例:How do we allocate a 2-D array using One malloc statement

    【讨论】:

      【解决方案3】:

      这是必需的,因为 C 没有垃圾收集器。 一旦您使用malloc 或类似函数分配内存,只要您的程序正在运行,它就会被标记为“正在使用”。

      如果您在程序中不再持有指向该内存的指针,则无关紧要。 C 语言中没有机制可以检查这一点并自动释放内存。

      此外,当您使用malloc 分配内存时,该函数不知道您将内存用于什么用途。对于分配器,它只是字节。

      因此,当您free 一个指针(或指针数组)时,没有逻辑可以“意识到”这些是包含内存地址的指针。

      这就是 C 语言的简单设计方式:动态内存管理几乎1 完全是手动的 - 留给程序员,因此每次调用 malloc 都必须调用 free


      1 C 语言确实处理了一些在程序中动态分配内存所需的更繁琐的任务,例如查找从何处获得所需大小的空闲连续内存块。 p>

      【讨论】:

        【解决方案4】:

        让我们举个简单的例子:

        int **ptr = malloc(2*sizeof *ptr);
        int *foo = malloc(sizeof *foo);
        int *bar = malloc(sizeof *bar);
        ptr[0] = foo;
        ptr[1] = bar;
        free(ptr);
        

        如果您的建议得到实施,foobar 现在将是悬空指针。如果您只想释放ptr,您将如何解决这种情况?

        【讨论】:

        • 这是一个反事实的例子
        • @toohonestforthissite “如果您的建议得到实施”
        • 我可以阅读(甚至理解)。我的反对意见是,foobar 都不是悬空指针,对于原始代码,也没有悬空指针,因为在 array 指向的对象 已被释放后,它确实不存在了`。 FWIW:悬空指针是指向未分配内存的指针。
        • @toohonestforthissite OP:建议调用free(ptr) 也应该释放指针ptr[0]ptr[1]。这将使foobar 成为悬空指针。
        • @Broman:啊,现在我明白他的意思了。但是,如果 OP 的建议得到实施,唯一合理的做法是标记 foobar 空指针(或以其他方式“指向无处)。就 OP 的问题没有得到很好的研究和思想。说,它没有只要有一个指向它的指针,GC 一个对象就有意义。但是 OP 明确显示了一个示例,其中 no 进一步指向 malloced 对象的指针使得这个答案毫无意义。
        猜你喜欢
        • 1970-01-01
        • 2014-08-08
        • 1970-01-01
        • 2018-07-31
        • 1970-01-01
        • 1970-01-01
        • 2015-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多