无法释放内存分配的一维和二维数组

时间:2014-09-28 13:50:48

标签: c arrays free dynamic-allocation

我正在研究一个数值程序来近似双曲方程的解。

我必须在for循环的每次迭代中为两个1d数组和两个2d数组分配内存。所以我在每次迭代中都分配了内存和free内存。

代码是

int main()
{
    int mesh, n_max, m_max;
    int i;
    double v, delta_t, delta_x, lambda;
    double *t, *x, **u, **u_exact, error[MAX_MESH]; 

    for (mesh = 0; mesh < MAX_MESH; mesh++) {
        m_max = pow(2, 5) * pow(2, mesh);
        n_max = 16 * m_max;

        t = vector_alloc((n_max + 1) * sizeof(double));
        x = vector_alloc((m_max + 2) * sizeof(double));
        u = matrix_alloc(m_max + 2, n_max);
        u_exact = matrix_alloc(m_max + 2, n_max);

        //functions manipulating t, x, u, u_exact

        free(t);
        free(x);
        for (i = 0; i < m_max + 2; i++) free(u[i]);
        free(u);
        for (i = 0; i < m_max + 2; i++) free(u_exact[i]);
        free(u_exact);
    }

    return (0);

}

double *vector_alloc(int n)
{
    double *result; /* ponteiro para o vetor */

    result = malloc(n * sizeof(double));
    if (result == NULL) printf("Error: no memmory available");
    return(result);
}

double **matrix_alloc(int m, int n)
{
    int i;
    double **result; 

    /* Allocates matrix raws */
    result = malloc(m * sizeof(double *));
    if (result == NULL) {
        printf ("Error: no memmory available");
        return (NULL);
    }
    /* Allocates matrix columns */
    for (i = 0; i < m; i++) {
        result[i] = malloc(n * sizeof(double));
        if (result[i] == NULL) {
            printf ("Error: no memmory available");
            return (NULL);
        }
    }
    return (result);
}

free语句不起作用。如果我尝试仅free 1d阵列tx,则在第二次迭代后,我会收到segmentation fault错误。

如果只尝试free二维数组uu_exact,我会收到错误

*** glibc detected *** ./a.out: double free or corruption (!prev): 0x0900a968 ***

2 个答案:

答案 0 :(得分:0)

我怀疑你的内存不足。内存分配似乎在循环中呈指数级增长。

对于MAX_MESH为8,如果我们采用最后一次迭代,那将是最坏的情况:

我假设双倍大小是8个字节。

m_max = 2 ^ 12
n_max = 2 ^ 16

所需内存以字节为单位:
 t =(2 ^ 16 + 1)*(2 ^ 3)= 2 ^ 19 + 2 ^ 3
 x =(2 ^ 12 + 1)*(2 ^ 3)= 2 ^ 15 + 2 ^ 3
 u =(2 ^ 12 + 2)*(2 ^ 16)*(2 ^ 3)= 2 ^ 31 + 2 ^ 20(约)
 u_exact = 2 ^ 31 + 2 ^ 20(约)

为简洁起见,我遗漏了将每个行指针存储在u和u_exact计算中所需的内存。

查看u和u_exact所需的大量内存!

现在,如果您在32位系统中运行,那么您的进程肯定没有足够的虚拟内存可供使用。我希望有一个&#34; NULL&#34; malloc在矩阵分配函数中返回的指针。您是否正在检查返回值并打印类似于您在vector_alloc中执行的操作的错误消息(如下所示)?

double **matrix_alloc(int m, int n)
{
    int i;
    double **p = malloc(sizeof(double **) * m);   
    if(!p) {printf("matrix_alloc:: Unable to allocate memory!!! \n");}
    for (i = 0; i < m; i++)
    {
        p[i] = malloc(sizeof(double) * n);
        if(!p[i]) {printf("matrix_alloc:: Unable to allocate memory!!! \n");}

    }
   return p;
}

如果请求的分配很大(默认值为128 KB),malloc会调用mmap。请参阅http://man7.org/linux/man-pages/man3/malloc.3.html。 mmap受RLIMIT_DATA资源限制的限制。您可以通过运行命令&#34; ulimit -v&#34;来检查系统中进程的虚拟内存限制。如果它返回&#34;无限制&#34;那就没有限制了。

我们可以通过将MAX_MESH值减小到4(如果要检入32位机器)来确认内存是否有问题。如果你在64位机器上运行相同的程序,我希望它会很好,因为可用的虚拟内存必须足以使你的MAX_MESH值为8。

答案 1 :(得分:0)

代码耗尽内存,并输出错误,但仍然继续,好像分配有效!

代码需要更改uu_exact的释放。

// for (i = 0; i < m_max + 2; i++) free(u[i]);
if (u != NULL) for (i = 0; i < m_max + 2; i++) free(u[i]);

由于分配的矩阵指针和分配的部分列都丢失,因此以下内存泄漏。可以释放分配的部件或错误,如下所示。存在其他方法。

/* Allocates matrix columns */
for (i = 0; i < m; i++) {
    result[i] = malloc(n * sizeof(double));
    if (result[i] == NULL) {

        // add 2 lines
        do { free(result[i]); } while (i-- > 0);
        free(result);

        printf ("Error: no memmory available");
        return (NULL);
    }
}

对于数组大小使用size_t而不是int是C方式,因为int的大小不是调整内存大小时使用的确定类型。请注意,size_t是未签名的。

同时分配内存是另一种方法。这可能有alligmnet问题,因此接下来是2分配方法。

void matrix_free(double **ptr) {
  if (ptr) {
    free(*ptr);
    free (ptr);
  }
}

double **matrix_alloc(size_t m, size_t n) {
  double **result = malloc(m * sizeof *result);
  double *data = malloc(m * n * sizeof *data);
  if (result == NULL || data == NULL) {
    free(result);
    free(data);
    printf ("Error: no memmory available");
    return (NULL);
  }
  for (size_t i=0; i<m; i++) {
    result[i] = &data[i*n];
  }
  return result;
}

void foo(void) {
  double **mat = matrix_alloc(3,4);
  ...
  matrix_free(mat);
  mat = NULL;
}