You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确改写矩阵?矩阵内存分配与奇数提取问题求助

问题解答:提取矩阵奇数的内存管理与泄漏修复

问题描述

我创建了一个仅存储原矩阵中奇数的新矩阵,初始时该矩阵的第二维度为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:11:11