【问题标题】:How to free my double pointer allocated with malloc in another function如何在另一个函数中释放我用 malloc 分配的双指针
【发布时间】:2019-10-26 02:34:55
【问题描述】:

我想释放双指针,问题是我收到另一个双指针作为参数,它实际上复制了我想要释放的那个,但这意味着它实际上并没有释放原始指针,所以我该如何释放原来在另一个函数中。

我尝试过传递一个双指针作为参数和一个指向这个双指针的指针,但这些都不起作用。

int main(){

    int ** matrix;
    int rows = 5;
    int cols = 6;
    matrix = createMatrix(rows, cols);
    printf("%d\n", matrix[2][3]);
    freeMatrix(matrix, rows);
    printf("%d\n", matrix[2][3]);
}
int** createMatrix(int row, int col){
    int **m = (int **)malloc(row * sizeof(int*));
    for(int x = 0; x < row; x++){
        m[x] = (int *)malloc(col * sizeof(int));
    }
    return m;
}
void freeMatriz(int **m, int row){
    for(int x = 0; x < row; x++){
        free(m[x]);
    }
    free(m);
}

我试图打印一个位置,比如说在 free 之前和之后的 matrix[2][3];但是在打印后它不应该两次打印数字,因为它应该释放内存中的空间,这显然没有发生。

【问题讨论】:

  • "我试图打印一个位置" --> 代码缺少打印。贴出真实代码。
  • 我很抱歉,因为它说我不应该发布我跳过那部分的所有代码,我的坏病修复它
  • 为什么“不应该发布所有代码”?
  • 您的 void freeMatriz(int **m, int row) {...} 函数没有问题。有什么问题? (当然,除非您的其中一项分配失败了——而且您无法分辨)。另外,malloc 的返回不需要强制转换,没有必要。见:Do I cast the result of malloc?
  • 在matrix[2][3] 位置上从来没有任何东西开始(除了未初始化的内存)您通过尝试在free() 之后访问该内存来调用 Undefined Behavior -- 所以任何事情都可能发生——包括看起来工作正常……

标签: c pointers matrix double-pointer


【解决方案1】:

除了

中的错别字
void freeMatriz(int **m, int row)
              ^

这正确地释放了内存。释放矩阵后的 printf 实际上应该导致访问冲突。当使用更大的 1024x2048 矩阵进行测试时,会发生这种情况。我的理论如下...

  1. 内存尚未回收,仍在程序范围内...
  2. 垃圾收集或其他东西的某种延迟..哈哈

我将把它留给可能知道为什么第二个 printf 使用如此小的内存空间来分配这样做的人.. ;) 很想知道确切的原因..

如果您使用调试器单步执行此操作,您将看到内存确实被正确释放,如果使用调试器单步执行,第二个 printf 会导致访问冲突......所以它必须与内核有关...... :)

如果您查看任务管理器中的工作集和内存分配,并在 free 之前放置一个 system("pause") 或 getchar()(您想要的任何类型的中断).. 您可以分配一个大矩阵,签入任务管理器...恢复程序(空闲后再次休息)。你会看到内存正在被释放。 :)

【讨论】:

  • 是的,对不起,我有西班牙语的代码,不得不翻译它才能把它贴在这里,忘了翻译那个,谢谢我在一个在线编译器中运行它,我在终端上检查了一下看看它打印了什么
【解决方案2】:

您的两个主要问题是:

  1. 您未能验证每个分配的返回,因此malloc 可能失败并且您无法知道;和
  2. 为整数值分配存储空间后,您无法初始化内存,从而使内存保留了该内存位置碰巧出现的任何垃圾值(您可以,对于整数分配,使用calloc同时分配和初始化,或使用memset 来做同样的事情)

您在free() 之前访问matrix[2][3] 的尝试只是访问一个未初始化的4 字节内存,其中包含碰巧存在的任何位。您在free() 之后访问matrix[2][3] 的尝试调用未定义的行为。在free()之后,你就不能再有效地访问已经被释放的内存了。

如果分配,则必须验证...不是如果 malloc 无法返回NULL 的问题,而是何时 @ 987654331@ 无法返回 NULL。要处理失败情况,您必须始终检查您使用的分配函数的返回(就像您对每个 input 函数所做的那样)。很简单,如果malloc 返回NULL 分配失败。所以只需检查一下,例如

int **creatematrix (int row, int col)
{
    int **m = malloc (row * sizeof *m);

    if (!m) {                   /* if you allocate -- you must VALIDATE */
        perror ("malloc-m");
        return NULL;
    }

    for (int x = 0; x < row; x++) {
        if (!(m[x] = malloc (col * sizeof *m[x]))) {    /* ditto */
            perror ("malloc-m[x]");
            while (x--)         /* on error free any allocated memory */
                free (m[x]);
            free (m);           /* before returing NULL */
            return NULL;
        }
    }

    return m;
}

(注意:在返回NULL 之前,您应该free() 分配到该点的任何内存,以防止在返回NULL 时发生内存泄漏)

在您的调用函数(此处为main())中,您需要验证creatematrix 函数的返回以确定分配的成功/失败 -- 在您使用内存之前,例如

int main (void) {

    int **matrix,
        rows = 5,
        cols = 6;

    if (!(matrix = creatematrix (rows, cols)))  /* VALIDATE allocations */
        exit (EXIT_FAILURE);

    for (int i = 0; i < rows; i++) {        /* loop initializing all values */
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
            printf (" %3d", matrix[i][j]);  /* output all values */
        }
        putchar ('\n');
    }

    freematrix (matrix, rows);              /* free all allocated memory */
}

现在你可以free()所有内存(除了'z'的错字而不是'x'你做得正确)。总而言之,您可以这样做:

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

int **creatematrix (int row, int col)
{
    int **m = malloc (row * sizeof *m);

    if (!m) {                   /* if you allocate -- you must VALIDATE */
        perror ("malloc-m");
        return NULL;
    }

    for (int x = 0; x < row; x++) {
        if (!(m[x] = malloc (col * sizeof *m[x]))) {    /* ditto */
            perror ("malloc-m[x]");
            while (x--)         /* on error free any allocated memory */
                free (m[x]);
            free (m);           /* before returing NULL */
            return NULL;
        }
    }

    return m;
}

void freematrix (int **m, int row)
{
    for (int x = 0; x < row; x++)
        free (m[x]);

    free (m);
}

int main (void) {

    int **matrix,
        rows = 5,
        cols = 6;

    if (!(matrix = creatematrix (rows, cols)))  /* VALIDATE allocations */
        exit (EXIT_FAILURE);

    for (int i = 0; i < rows; i++) {        /* loop initializing all values */
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
            printf (" %3d", matrix[i][j]);  /* output all values */
        }
        putchar ('\n');
    }

    freematrix (matrix, rows);              /* free all allocated memory */
}

使用/输出示例

$ ./bin/freematrix
   0   1   2   3   4   5
   6   7   8   9  10  11
  12  13  14  15  16  17
  18  19  20  21  22  23
  24  25  26  27  28  29

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此 (2) 当不再需要它时可以释放。

您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。

对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。

$ valgrind ./bin/freematrix
==17080== Memcheck, a memory error detector
==17080== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17080== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==17080== Command: ./bin/freematrix
==17080==
   0   1   2   3   4   5
   6   7   8   9  10  11
  12  13  14  15  16  17
  18  19  20  21  22  23
  24  25  26  27  28  29
==17080==
==17080== HEAP SUMMARY:
==17080==     in use at exit: 0 bytes in 0 blocks
==17080==   total heap usage: 6 allocs, 6 frees, 160 bytes allocated
==17080==
==17080== All heap blocks were freed -- no leaks are possible
==17080==
==17080== For counts of detected and suppressed errors, rerun with: -v
==17080== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认您已释放已分配的所有内存并且没有内存错误。

查看一下,如果您还有其他问题,请告诉我。

【讨论】:

  • 好的,谢谢我已经调查过了,只有很多信息,但我明白我需要如何检查 malloc 并且我一直在研究为什么我的程序没有按照它应该的方式工作有了这个信息,谢谢
  • 祝你好运。只需逐行和逐个字符地获取所有内容。了解为什么要使用每个。 (也知道if (!(ptr = malloc (...))) 只是ptr = malloc (...); if (ptr != NULL) {...的简写} C 中有很多东西要消化,而且这不是一场比赛,所以请放慢脚步,享受学习的乐趣:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-01
  • 2013-10-31
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多