首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何释放在另一个函数中使用malloc分配的双指针

如何释放在另一个函数中使用malloc分配的双指针
EN

Stack Overflow用户
提问于 2019-10-26 10:34:55
回答 2查看 407关注 0票数 0

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

我试着传递一个双指针作为参数,也试着传递一个指向这个双指针的指针,但是都没有成功。

代码语言:javascript
复制
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);
}

我试图打印一个位置,假设在释放之前和之后使用matrix2;,但是两次都打印数字,当打印之后,它不应该打印,因为内存中的空间应该被释放,显然没有发生。

EN

回答 2

Stack Overflow用户

发布于 2019-10-26 11:12:34

中的打字错误

代码语言:javascript
复制
void freeMatriz(int **m, int row)
              ^

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

  1. 内存尚未回收,仍在程序可用范围内...
  2. 垃圾收集中的某种延迟或其他..lol

我将把这个问题留给可能知道为什么第二个printf能够在如此小的内存空间下工作的人来做。;)很想知道确切的原因..

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

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

票数 2
EN

Stack Overflow用户

发布于 2019-10-26 11:10:59

你的两个主要问题是:

  1. 您无法验证每个分配的返回,因此malloc可能已失败,您将无法知道;和
  2. 为整数值分配存储后,您无法初始化内存,使内存保留该内存位置恰好存在的任何垃圾值(您可以使用calloc同时分配和初始化,或者使用memset执行相同的操作)

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

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

代码语言:javascript
复制
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函数的返回,以确定allocate -的成功/失败,例如

代码语言:javascript
复制
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' )。总之,你可以这样做:

代码语言:javascript
复制
#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 */
}

示例使用/输出

代码语言:javascript
复制
$ ./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

内存使用/错误检查

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

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

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

代码语言:javascript
复制
$ 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)

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

仔细检查一下,如果你还有其他问题,请告诉我。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58567601

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档