如何正确改写矩阵?矩阵内存分配与奇数提取问题求助
问题解答:提取矩阵奇数的内存管理与泄漏修复
问题描述
我创建了一个仅存储原矩阵中奇数的新矩阵,初始时该矩阵的第二维度为1。请问我是否需要对每行执行realloc操作?如果需要,具体该如何实现?此外,在malloc两个矩阵时出现了错误。相关函数代码如下:
int i,j; b->matr=(Line*)calloc(a->lines,sizeof(Line)); for (i=0;i<a->lines;i++) { b->matr[i].arr=(int*)malloc((a->matr[i].n)*sizeof(int)); } for(i=0;i<a->lines;i++) { for(j=0;j<a->matr[i].n;j++) { if (a->matr[i].arr[j]%2 != 0) { b->matr[i].arr[j]=a->matr[i].arr[j]; printf("%d",b->matr[i].arr[j]); printf(" "); } } printf("\n"); }
Valgrind检测结果如下:
Matrix: 2 1 2 2 4 5 New Matrix: 1 5 ==11435== ==11435== HEAP SUMMARY: ==11435== in use at exit: 24 bytes in 3 blocks ==11435== total heap usage: 10 allocs, 7 frees, 2,192 bytes allocated ==11435== ==11435== 24 bytes in 3 blocks are definitely lost in loss record 1 of 1 ==11435== at 0x48427B5: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==11435== by 0x10937E: newMatr (in /home/students/c/chmel.da/inf2/lab1/prog1) ==11435== by 0x109255: main (in /home/students/c/chmel.da/inf2/lab1/prog1)
我尝试对每行进行realloc操作,但没有取得任何效果。
解答
1. 是否需要realloc?
需要。当前代码按原矩阵每行长度分配内存,但实际存储的奇数数量通常少于原长度,会造成内存浪费;如果初始按维度1分配,更需要realloc动态扩容来匹配实际存储的奇数个数。
2. 具体实现方案
方案一:先统计奇数个数再分配内存(更高效)
先遍历原矩阵统计每行奇数数量,直接分配对应大小的内存,避免多次realloc操作:
int i, j, count; // 为新矩阵的行结构分配内存 b->matr = (Line*)calloc(a->lines, sizeof(Line)); if (!b->matr) { // 处理内存分配失败,比如返回错误码或终止程序 perror("calloc failed"); return; } for (i = 0; i < a->lines; i++) { count = 0; // 第一步:统计当前行的奇数个数 for (j = 0; j < a->matr[i].n; j++) { if (a->matr[i].arr[j] % 2 != 0) { count++; } } // 为当前行分配对应大小的内存 b->matr[i].arr = (int*)malloc(count * sizeof(int)); if (!b->matr[i].arr) { perror("malloc failed"); // 已分配的内存需要提前释放,避免泄漏 for (int k = 0; k < i; k++) { free(b->matr[k].arr); } free(b->matr); return; } b->matr[i].n = count; // 更新新矩阵该行的有效元素数 // 第二步:填充奇数到新矩阵 int idx = 0; for (j = 0; j < a->matr[i].n; j++) { if (a->matr[i].arr[j] % 2 != 0) { b->matr[i].arr[idx++] = a->matr[i].arr[j]; printf("%d ", b->matr[i].arr[idx-1]); } } printf("\n"); }
方案二:初始按维度1分配,动态realloc扩容
如果必须初始按维度1分配再调整,可按以下方式实现:
int i, j; b->matr = (Line*)calloc(a->lines, sizeof(Line)); if (!b->matr) { perror("calloc failed"); return; } for (i = 0; i < a->lines; i++) { // 初始分配1个int的内存 b->matr[i].arr = (int*)malloc(1 * sizeof(int)); if (!b->matr[i].arr) { perror("malloc failed"); // 清理已分配内存 for (int k = 0; k < i; k++) { free(b->matr[k].arr); } free(b->matr); return; } b->matr[i].n = 0; // 当前有效元素数为0 for (j = 0; j < a->matr[i].n; j++) { if (a->matr[i].arr[j] % 2 != 0) { // 扩容:有效元素数+1 int* temp = (int*)realloc(b->matr[i].arr, (b->matr[i].n + 1) * sizeof(int)); if (!temp) { perror("realloc failed"); // 清理当前行及之前的内存 free(b->matr[i].arr); for (int k = 0; k < i; k++) { free(b->matr[k].arr); } free(b->matr); return; } b->matr[i].arr = temp; b->matr[i].arr[b->matr[i].n] = a->matr[i].arr[j]; b->matr[i].n++; // 更新有效元素数 printf("%d ", b->matr[i].arr[b->matr[i].n - 1]); } } // 如果该行无奇数,释放初始分配的内存,避免浪费 if (b->matr[i].n == 0) { free(b->matr[i].arr); b->matr[i].arr = NULL; } printf("\n"); }
3. 内存泄漏修复
Valgrind显示的泄漏是因为分配的内存未释放,需在使用完新矩阵后执行释放操作:
// 释放新矩阵的每行内存 for (int i = 0; i < b->lines; i++) { if (b->matr[i].arr) { free(b->matr[i].arr); b->matr[i].arr = NULL; } } // 释放行结构数组 free(b->matr); b->matr = NULL; b->lines = 0; // 重置矩阵行数,避免野指针
内容的提问来源于stack exchange,提问作者dima fgb
相关产品推荐
相关产品推荐

