C中的内存泄漏,结构中的二维数组
Memory leak in C, 2d array in struct
我真的需要一些关于内存泄漏的帮助。我盯着我的代码看了一段时间,但仍然无法找出这些漏洞在哪里。我想我正在释放一切,甚至有时是不必要的,但还是有一些东西。
代码
#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='[=10=]';
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 错误是不可取的。
感谢您的帮助!
一个问题是:
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
中的一项分配的一些数据,因此您试图释放数据两次,这是错误的。对此的简单解决方案是不为 res.data
.
调用 _2d_array_free
最后一点关于样式和命名的注意事项:您真的应该避免使用带有前导下划线的符号名称。如果您不小心,您可能会使用保留符号(下划线后跟一个大写字母或另一个下划线)。前导下划线通常由编译器和标准库在内部使用。
我真的需要一些关于内存泄漏的帮助。我盯着我的代码看了一段时间,但仍然无法找出这些漏洞在哪里。我想我正在释放一切,甚至有时是不必要的,但还是有一些东西。
代码
#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='[=10=]';
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 错误是不可取的。
感谢您的帮助!
一个问题是:
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
中的一项分配的一些数据,因此您试图释放数据两次,这是错误的。对此的简单解决方案是不为 res.data
.
_2d_array_free
最后一点关于样式和命名的注意事项:您真的应该避免使用带有前导下划线的符号名称。如果您不小心,您可能会使用保留符号(下划线后跟一个大写字母或另一个下划线)。前导下划线通常由编译器和标准库在内部使用。