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

C语言动态分配二维矩阵出现段错误,求原因分析

C语言二维矩阵动态分配的段错误问题分析

我是C语言初学者,正在学习二维矩阵的动态分配。在main函数中用10和11作为测试尺寸时,insert_values函数执行时能正常输出,但调用print_values函数会触发段错误,请求帮忙分析问题原因。

代码示例

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

void insert_values(int **arr, int dim, int size);

void resize(int ***arr, int dim) {
    if (*arr == NULL) { 
        *arr = (int **)malloc(dim * sizeof(int *));
        if (!*arr) return; 
    } 
    else { 
        *arr = (int **)realloc(*arr, dim * sizeof(int *));
        if (*arr == NULL) return; 
    }

    for (int i = 0; i < dim; i++) { 
        if ((*arr)[i] == NULL) { 
            (*arr)[i] = (int *)malloc(dim * sizeof(int));

            if (!(*arr)[i]) return; 

            break;
        }
        else { //如果该位置已存在则重新分配
            (*arr)[i] = (int *)realloc(**arr, dim * sizeof(int));
 
            if ((*arr)[i] == NULL) return;
        }
    }
}
    
void insert_values(int **arr, int dim, int size) {
    if (size > dim) {
        resize(&(arr), size);
    }

    int x;
    int y;

    for(x = 0; x < size; x++) {
        for (y = 0; y < size; y++) {
            arr[x][y] = x + y;
            printf("%d |", arr[x][y]);
        }

        printf("\n");
    }
}

void print_values(int **arr, int size) {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            printf("%d |", *(arr+i)[j]);
        }

        printf("\n");
    }
}

int main(int argc, char *argv[]) {
    int **x =  (int**)malloc(10 * sizeof(*x));

    if (!x) { return 0; }

    for (int i = 0; i < 10; i++) {
        x[i] = (int*)malloc(10 * sizeof(int));
    }

    insert_values(x, 10, 11);
    print_values(x, 11);

    for (int i = 0; i < 10; i++) {
        free(x[i]);
    }

    free(x);
}

运行输出

0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |
1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |
2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |
3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |
4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |
5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |
6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |
7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |
8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |
9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |
10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |
-533986992 |-533955728 |

问题原因分析

1. 函数参数传递错误,主函数指针未更新

insert_values中调用resize(&arr, size)时,arr是函数的形参,修改形参的地址不会同步到main函数的x指针。也就是说,resize内部把arr扩容到11个指针,但main里的x仍是原来仅10个指针的数组。后续print_values用x访问第11个元素(x[10])属于数组越界,触发非法内存访问。

2. resize函数循环逻辑完全错误

  • 循环遇到(*arr)[i] == NULL时,分配空间后直接break,仅处理第一个符合条件的元素,其余行(包括新增的行)都未正确分配/扩容。
  • realloc参数错误:realloc(**arr, dim * sizeof(int))中,**arr是arr[0][0]的值,而非要扩容的行指针(*arr)[i],会错误修改行指针指向,破坏内存结构。

3. print_values运算符优先级错误

*(arr+i)[j]的写法存在优先级问题:[]优先级高于*,表达式等价于*(arr+i+j),即访问arr[i+j]的首元素,而非第i行第j列的元素。当i=10时,arr+i+j指向arr[10],超出main中x的数组范围,触发段错误。

4. 内存管理漏洞

  • 扩容后新增的行指针未被释放,造成内存泄漏。
  • realloc失败时会丢失原有行指针,同样导致内存泄漏。

修正建议

  1. 修改insert_values参数为指针的指针,确保resize能修改主函数的原始指针:

    void insert_values(int ***arr, int dim, int size) {
        if (size > dim) {
            resize(arr, size);
        }
        // 后续访问改为 (*arr)[x][y]
    }
    // main中调用:insert_values(&x, 10, 11);
    
  2. 修复resize循环逻辑,遍历所有行正确处理:

    void resize(int ***arr, int new_dim) {
        int old_dim = (*arr != NULL) ? 10 : 0; // 示例中原维度为10,更严谨的做法是传入原维度
        // 先扩容指针数组
        int **tmp = realloc(*arr, new_dim * sizeof(int *));
        if (!tmp) return;
        *arr = tmp;
        // 处理每一行
        for (int i = 0; i < new_dim; i++) {
            if (i >= old_dim) {
                (*arr)[i] = malloc(new_dim * sizeof(int));
            } else {
                int *row_tmp = realloc((*arr)[i], new_dim * sizeof(int));
                if (!row_tmp) return;
                (*arr)[i] = row_tmp;
            }
        }
    }
    
  3. 修正print_values的访问方式:

    void print_values(int **arr, int size) {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                printf("%d |", arr[i][j]);
            }
            printf("\n");
        }
    }
    
  4. 根据最终矩阵尺寸释放所有行:

    // main中print后释放11行
    for (int i = 0; i < 11; i++) {
        free(x[i]);
    }
    free(x);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:40:57