2016-11-13 108 views
0

我真的需要一些内存泄漏的帮助。我一直盯着我的代码一段时间,仍然无法找出那些泄漏。我想我可以解放所有东西,甚至有时候是不必要的,但是还有一些东西。C中的内存泄漏,结构中的二维数组

代码

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

struct Matrix{ 
    int **data; 
    int rows; 
    int columns; 
}; 

struct Matrix matrix_op(struct Matrix, struct Matrix, char); 
int** _2d_array(int,int); 
void print_matrix(struct Matrix); 
void _2d_array_free(int**, int); 
void _scalar_mul(struct Matrix*, int); 

int** _2d_array(int x,int y){ 
    int** arr; 
    arr = malloc(sizeof(int*)*x); 
    for(int i = 0; i<x;++i){ 
     arr[i] = malloc(sizeof(int)*y); 
    } 
    return arr; 
} 
void _scalar_mul(struct Matrix* a, int s){ 
    for (int x = 0; x < a->rows; ++x) { 
     for (int y = 0; y < a->columns; ++y) 
      a->data[x][y] *= s; 
    } 
} 

void _2d_array_free(int** array, int x){ 
    for (int i = 0; i < x; ++i) { 
     free(array[i]); 
    } 
    free(array); 
} 

void exit_err(int err, char* message){ 
    fprintf(stderr,message); 
    exit(err); 
} 

struct Matrix read_matrix(int x, int y){ 
    struct Matrix matrix; 
    matrix.rows = x; 
    matrix.columns = y; 
    matrix.data = _2d_array(x,y); 
    for (int i = 0; i < x; ++i) { 
     for (int j = 0; j < y; ++j) { 
      if(scanf("%d", &matrix.data[i][j])==0) exit_err(100,"Error...\n"); 
     } 
    } 
    return matrix; 
} 

struct Matrix matrix_op(struct Matrix a, struct Matrix b, char op) { 
    struct Matrix res_matrix; 
    int** result; 
    if (op == '*') { 
     if(a.columns==b.rows) { 
      result = _2d_array(a.rows, b.columns); 
      for (int x = 0; x < a.rows; ++x) { 
       for (int y = 0; y < b.columns; ++y) { 
        int sum = 0; 
        for (int z = 0; z < a.columns; z++) { 
         sum += a.data[x][z] * b.data[z][y]; 
        } 
        result[x][y] = sum; 
       } 
      } 
     } 
     else exit_err(100,"Error...\n"); 
     res_matrix.data = result; 
     res_matrix.rows = a.rows; 
     res_matrix.columns = b.columns; 
    } else { 
     if (op == '-') { 
      _scalar_mul(&b,-1); 
     } 
     result = _2d_array(a.rows,a.columns); 
     for (int x = 0; x < a.rows; ++x) { 
      for (int y = 0; y < a.columns; ++y){ 
       result[x][y]=a.data[x][y]+b.data[x][y]; 
      } 
     } 
     res_matrix.data = result; 
     res_matrix.rows = a.rows; 
     res_matrix.columns = a.columns; 
    } 
    return res_matrix; 
} 

void print_matrix(struct Matrix matrix){ 
    printf("%d %d\n",matrix.rows, matrix.columns); 
    for(int x = 0; x<matrix.rows;++x){ 
     for(int y = 0; y<matrix.columns;++y){ 
      if(y==0)printf("%d", matrix.data[x][y]); 
      else printf(" %d",matrix.data[x][y]); 
     } 
     printf("\n"); 
    } 
} 

int main(){ 
    int x,y,count; 
    count=0; 
    char op='\0'; 
    struct Matrix* matrices = malloc(0); 
    while(1){ 
     scanf("%d %d", &x, &y); 
     matrices = realloc(matrices,sizeof(struct Matrix)*(++count)); 
     matrices[count-1]=read_matrix(x,y); 
     if(op=='-') { 
      _scalar_mul(&matrices[count - 1], -1); 
     }; 
     if(op=='*') { 
      struct Matrix result = matrix_op(matrices[count-2], matrices[count-1], op); 
      _2d_array_free(matrices[count-1].data, matrices[count-1].rows); 
      matrices[count-1] = result; 
      _2d_array_free(matrices[count-2].data, matrices[count-2].rows); 
      matrices[count-2].rows=0; 
     } 
     if(scanf("\n%c", &op)==EOF) break; 

    } 
    struct Matrix res; 
    res.data = _2d_array(3,3); 
    res.rows = 3; 
    res.columns = 3; 
    res = matrices[0]; 
    for (int i = 1; i < count; ++i) { 
     if(res.rows>0&&matrices[i].rows>0) { 
      struct Matrix tmp = matrix_op(res, matrices[i], '+'); 
      _2d_array_free(res.data, res.rows); 
      res.rows = 0; 
      res = tmp; 
     } 
     else if (res.rows==0){ 
      _2d_array_free(res.data, res.rows); 
      res.rows = 0; 
      res = matrices[i]; 
     } 
    } 
    print_matrix(res); 
    _2d_array_free(res.data, res.rows); 
    for (int j = 0; j < count; ++j) { 
     if(matrices[j].rows!=0){ 
      _2d_array_free(matrices[j].data,matrices[j].rows); 
     } 
    } 
    free(matrices); 
} 

Valgrind的出来:

==25== Invalid read of size 8 
==25== at 0x4008B5: _2d_array_free (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x401038: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== Address 0x51fc0d0 is 0 bytes inside a block of size 24 free'd 
==25== at 0x4C2BD57: free (vg_replace_malloc.c:530) 
==25== by 0x4008D7: _2d_array_free (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400F51: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== Block was alloc'd at 
==25== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299) 
==25== by 0x4007AC: _2d_array (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400936: read_matrix (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400D46: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== 
==25== Invalid free()/delete/delete[]/realloc() 
==25== at 0x4C2BD57: free (vg_replace_malloc.c:530) 
==25== by 0x4008BF: _2d_array_free (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x401038: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== Address 0x51fc130 is 0 bytes inside a block of size 28 free'd 
==25== at 0x4C2BD57: free (vg_replace_malloc.c:530) 
==25== by 0x4008BF: _2d_array_free (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400F51: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== Block was alloc'd at 
==25== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299) 
==25== by 0x4007DF: _2d_array (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400936: read_matrix (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400D46: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== 
==25== Invalid free()/delete/delete[]/realloc() 
==25== at 0x4C2BD57: free (vg_replace_malloc.c:530) 
==25== by 0x4008D7: _2d_array_free (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x401038: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== Address 0x51fc0d0 is 0 bytes inside a block of size 24 free'd 
==25== at 0x4C2BD57: free (vg_replace_malloc.c:530) 
==25== by 0x4008D7: _2d_array_free (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400F51: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== Block was alloc'd at 
==25== at 0x4C2AC3D: malloc (vg_replace_malloc.c:299) 
==25== by 0x4007AC: _2d_array (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400936: read_matrix (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== by 0x400D46: main (in /mnt/c/Users/wM/ClionProjects/hw4/main) 
==25== 
==25== 
==25== HEAP SUMMARY: 
==25==  in use at exit: 60 bytes in 4 blocks 
==25== total heap usage: 19 allocs, 19 frees, 432 bytes allocated 
==25== 
==25== LEAK SUMMARY: 
==25== definitely lost: 24 bytes in 1 blocks 
==25== indirectly lost: 36 bytes in 3 blocks 
==25==  possibly lost: 0 bytes in 0 blocks 
==25== still reachable: 0 bytes in 0 blocks 
==25==   suppressed: 0 bytes in 0 blocks 
==25== Rerun with --leak-check=full to see details of leaked memory 
==25== 
==25== For counts of detected and suppressed errors, rerun with: -v 
==25== ERROR SUMMARY: 7 errors from 3 contexts (suppressed: 0 from 0) 

输入

3 7 
-42 8 -62 0 7 46 3 
7 11 45 89 -39 -27 70 
-35 -5 0 -99 -50 -14 46 
+ 
3 7 
73 -88 -45 94 -41 -67 -66 
0 22 30 29 72 -91 76 
-95 -83 -46 -88 28 69 -62 

输出

3 7 
31 -80 -107 94 -34 -21 -63 
7 33 75 118 33 -118 146 
-130 -88 -46 -187 -22 55 -16 

输出是确定的,但内存泄漏和Valgrind的错误是不希望的。

感谢您的帮助!

+0

你怎么知道你有内存泄漏?何时何地以及如何分配内存?请尝试创建[最小化,完整和可验证示例](http://stackoverflow.com/help/mcve)并向我们显示。还包括您的输入以及问题中的预期和实际输出。 –

+2

我的C有点生疏,但我认为'free(array [i])'只释放第一个数组项,而不是整个数组。 – GolezTrol

回答

3

的一个问题是这样的:

struct Matrix res; 
res.data = _2d_array(3,3); 
res.rows = 3; 
res.columns = 3; 
res = matrices[0]; 

您定义res并初始化它,那么你重新分配matrices[0]它覆盖所有先前初始化的数据,包括指针到刚分配的数据。


另外:

_2d_array_free(res.data, res.rows); 
for (int j = 0; j < count; ++j) { 
    if(matrices[j].rows!=0){ 
     _2d_array_free(matrices[j].data,matrices[j].rows); 
    } 
} 

这里res.data指向分配给在matrices的一个条目,让你尝试两次释放的数据是错误的一些数据。简单的解决办法是不要拨_2d_array_free来代替res.data


最后大约风格和命名一个小纸条:你真的应该避免使用符号的名称与领先的下划线。如果您不小心,可以使用保留符号(下划线后跟大写字母或其他下划线)。主要的下划线通常由编译器和标准库在内部使用。