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

矩阵保留指定行并释放内存问题:select_rows函数致程序崩溃

二维矩阵行选择函数崩溃问题排查与修复

核心问题分析

1. 参数类型不匹配

select_rows 声明的第一个参数是 int ***a(指向二维指针的指针),但 main 中传入的是 a(int** 类型的二维指针),直接导致指针类型错误,触发内存访问崩溃。

2. 二维数组访问错误

函数中直接用 a[i][j] 访问元素,但 a 是三级指针,必须先解引用得到二维数组指针,即 (*a)[i][j],否则会访问非法内存地址。

3. 内存释放循环越界

释放行内存的循环条件 i <= *n 错误:原矩阵行数为 *n,行下标范围是 0 ~ *n-1,i <= *n 会访问超出数组范围的内存,引发未定义行为。正确条件应为 i < *n。

4. 逻辑分支顺序错误

if (*a == NULL) 后的 return 语句会跳过后续的行数更新逻辑,且判断位置不合理,应在函数开头先做输入合法性校验。

5. create 函数的潜在问题

  • 内存分配失败时返回 1,不符合 int** 返回类型要求,应返回 NULL;
  • 检查 calloc 结果时错误判断 a == NULL,实际需判断 a[i] == NULL;
  • 若某行分配失败,未释放已分配的前序行,会造成内存泄漏。

修正后的完整代码

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

void select_rows(int ***a, int *n, int m, int l, int r) {
    // 输入合法性校验
    if (a == NULL || *a == NULL || l < 0 || r >= *n || l > r) {
        return;
    }

    int new_row_count = r - l + 1;
    // 移动保留行到数组起始位置(直接移指针,无需逐元素拷贝)
    for (int i = 0; i < new_row_count; ++i) {
        (*a)[i] = (*a)[l + i];
    }

    // 释放不需要的行内存
    for (int i = r + 1; i < *n; ++i) {
        free((*a)[i]);
    }

    // 调整指针数组大小,彻底释放多余内存
    int **temp = realloc(*a, new_row_count * sizeof(int*));
    if (temp != NULL) {
        *a = temp;
    }

    // 更新矩阵行数
    *n = new_row_count;
}

int **create(int n, int m, int L, int R) {
    int **a = malloc(n * sizeof(int *));
    if (a == NULL) {
        return NULL;
    }

    for (int i = 0; i < n; ++i) {
        a[i] = calloc(m, sizeof(int));
        if (a[i] == NULL) {
            // 释放已分配行,避免内存泄漏
            for (int j = 0; j < i; ++j) {
                free(a[j]);
            }
            free(a);
            return NULL;
        }
    }

    srand((unsigned int)time(NULL));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            a[i][j] = rand() % (R - L + 1) + L;
        }
    }
    return a;
}

void print(int **a, int n, int m) {
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int n = 5, m = 4, L = -1, R = 3;
    int **a = create(n, m, L, R);
    if (a == NULL) {
        printf("矩阵创建失败\n");
        return 1;
    }

    printf("原矩阵:\n");
    print(a, n, m);

    int l = 2, r = 3;
    select_rows(&a, &n, m, l, r);

    printf("保留第%d到%d行后的矩阵:\n", l, r);
    print(a, n, m);

    // 释放最终矩阵内存
    for (int i = 0; i < n; ++i) {
        free(a[i]);
    }
    free(a);

    return 0;
}

关键修正说明

  • 修正参数传递:main 中传入 &a 匹配三级指针参数;
  • 改用指针移动替代逐元素拷贝,提升效率且避免内存错误;
  • 增加输入合法性检查,拦截非法下标操作;
  • 补充 realloc 调整指针数组大小的逻辑,彻底释放多余内存;
  • 修复 create 函数的内存泄漏问题与错误返回值;
  • 补充完整的内存释放逻辑,避免内存泄漏。

内容的提问来源于stack exchange,提问作者SF40

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:25:59