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

使用memset初始化C语言二维数组时出现异常,请求排查代码问题

问题排查与修复方案

咱们一步一步拆解你代码里的问题,这几个点叠加起来导致了打印时的异常:

1. 栈上局部数组返回后直接失效

你在twoDArray()里定义的int *arr[5];是栈上的局部变量,当函数执行完毕返回时,栈内存会被操作系统回收。main函数里接收这个返回值后去访问,本质是在访问已经被释放的内存,属于未定义行为——这本身就会引发各种奇怪的错误,包括后续的打印异常。

2. memset的使用完全错误

你想用memset初始化数组元素,但误解了二维指针数组的结构:

  • arr是一个包含5个指针的数组,每个指针指向一块堆上的int数组(大小为2)。
  • 你调用memset(arr, 0, 2 * 5 * sizeof(arr[0][0]))时,直接把arr这个指针数组的内存清零了——这等于把每个指向堆内存的指针都改成了NULL(0)。之后再访问arr[r][c],就是通过空指针去访问内存,必然触发异常。
  • 另外,memset的第三个参数也错了:就算你要清零指针数组本身,大小应该是5 * sizeof(int*),但这根本不是你想要的(你要清零的是每个指针指向的int数组,不是指针本身)。

3. 初始化循环的越界问题

你注释掉了外层的for (r = 0; r < 5; r++),导致下面的arr[r][c] = 1;里的r值是5(因为之前malloc的循环结束后r已经自增到5),这时候访问arr[5]已经超出了数组的合法下标范围(数组下标是0-4),属于越界访问,会破坏内存结构。


修复后的代码示例

针对上面的问题,我调整了代码,你可以参考:

#include "stdafx.h"
#include "stdlib.h"
#include "string.h" // 需要包含这个头文件才能使用memset

// 动态分配二维数组的正确方式:先分配指针数组,再分配每个子数组
int **twoDArray() {
    // 先在堆上分配指针数组(避免返回栈变量)
    int **arr = (int**)malloc(5 * sizeof(int*));
    if (!arr) { // 检查malloc是否成功,避免空指针
        return NULL;
    }

    // 为每个指针分配子数组
    for (int r = 0; r < 5; r++) {
        arr[r] = (int*)malloc(2 * sizeof(int));
        if (!arr[r]) { // 分配失败时要释放已分配的内存,避免泄漏
            for (int i = 0; i < r; i++) {
                free(arr[i]);
            }
            free(arr);
            return NULL;
        }
    }

    // 用memset初始化每个子数组的元素为1,也可以逐个赋值
    for (int r = 0; r < 5; r++) {
        memset(arr[r], 1, 2 * sizeof(int));
        // 打印初始化后的值
        for (int c = 0; c < 2; c++) {
            printf("%d \n", arr[r][c]);
        }
    }

    // 现在用memset把每个子数组清零(注意是针对arr[r],不是arr本身)
    for (int r = 0; r < 5; r++) {
        memset(arr[r], 0, 2 * sizeof(int));
    }

    // 打印清零后的值
    for (int r = 0; r < 5; r++) {
        for (int c = 0; c < 2; c++) {
            printf("%d \n", arr[r][c]);
        }
    }

    return arr;
}

int main() {
    int **arr = twoDArray();
    if (!arr) { // 检查数组是否分配成功
        return 1;
    }

    // 再次修改并打印
    for (int r = 0; r < 5; r++) {
        for (int c = 0; c < 2; c++) {
            arr[r][c] = 0;
            printf("%d \n", arr[r][c]);
        }
    }

    // 记得释放内存,避免内存泄漏
    for (int r = 0; r < 5; r++) {
        free(arr[r]);
    }
    free(arr);

    return 0;
}

关键修复点总结

  • 把指针数组arr分配在堆上,而不是栈上,这样函数返回后内存依然有效。
  • 使用memset时,要针对每个子数组arr[r]操作,而不是直接操作指针数组arr。
  • 修复了初始化循环的越界问题,确保循环覆盖所有合法的数组元素。
  • 添加了malloc失败的检查和内存释放逻辑,避免内存泄漏和崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:01:45