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

Visual Studio 2019运行C语言代码时SetArr函数触发Access violation错误求助

解决Access Violation错误的分析与修正

先直接点出核心问题:你的代码触发访问冲突的根源是全局指针arr1根本没被正确初始化,再加上函数参数传递的逻辑错误,导致程序试图访问非法的内存地址。

具体问题拆解

  1. 传值调用的陷阱
    你的zeros函数接收的是int** arr参数,这是典型的传值调用——函数内部修改的只是这个参数的副本,完全不会影响外部的全局变量arr1。调用zeros(arr1, 2, 3)后,arr1仍然是一个未初始化的野指针,后续在SetArr里访问arr1[i][j]必然会触发访问冲突。

  2. 函数内误用全局变量
    SetArr函数明明接收了arr参数,但你却在函数里直接操作全局的arr1,这不仅违背了函数设计的初衷,还让指针问题变得更严重。

  3. 全局循环变量的潜在风险
    你用了全局的i和j,虽然这次不是直接诱因,但在嵌套循环或者多线程场景下,很容易引发逻辑混乱,建议改用局部变量。

修正方案

下面给你两种可行的修正方式,你可以根据习惯选择:

方案1:让zeros返回分配好的指针

这种方式更直观,直接把分配完成的二维数组指针返回给调用者:

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

// 修改函数签名,返回分配好的二维数组指针
int** zeros(int rowNum, int colNum);
void SetArr(int** arr, int rowNum, int colNum);

// 仅保留必要的全局变量
int **arr1, **arr2;

int main() {
    arr1 = zeros(2, 3);
    // 必须检查内存分配是否成功
    if (arr1 == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    SetArr(arr1, 2, 3);
    
    // 使用完记得释放内存,避免内存泄漏
    for (int i = 0; i < 2; i++) {
        free(arr1[i]);
    }
    free(arr1);
    arr1 = NULL;
    
    return 0;
}

int** zeros(int rowNum, int colNum) {
    int** arr = (int**)malloc(sizeof(int*) * rowNum);
    if (arr == NULL) {
        return NULL;
    }
    // 使用局部循环变量i
    for (int i = 0; i < rowNum; i++) {
        arr[i] = (int*)malloc(sizeof(int) * colNum);
        // 若某一行分配失败,要回滚之前分配的内存
        if (arr[i] == NULL) {
            for (int j = 0; j < i; j++) {
                free(arr[j]);
            }
            free(arr);
            return NULL;
        }
        // 如果需要把数组初始化为0,加上这行
        // memset(arr[i], 0, sizeof(int)*colNum);
    }
    return arr;
}

void SetArr(int **arr, int rowNum, int colNum) {
    // 使用局部循环变量
    for (int i = 0; i < rowNum; i++) {
        for (int j = 0; j < colNum; j++) {
            // 把input设为局部变量,避免全局变量污染
            int input;
            scanf_s("%d", &input);
            // 使用传入的arr参数,而非全局arr1
            arr[i][j] = input;
        }
    }
}

方案2:通过指针的指针修改外部变量

如果你不想用返回值,也可以传递指针的指针(int***),让函数直接修改外部的指针变量:

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

// 修改函数签名,接收指针的指针
void zeros(int*** arr, int rowNum, int colNum);
void SetArr(int** arr, int rowNum, int colNum);

int **arr1, **arr2;

int main() {
    // 传入arr1的地址
    zeros(&arr1, 2, 3);
    if (arr1 == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }
    SetArr(arr1, 2, 3);
    
    // 释放内存
    for (int i = 0; i < 2; i++) {
        free(arr1[i]);
    }
    free(arr1);
    arr1 = NULL;
    
    return 0;
}

void zeros(int*** arr, int rowNum, int colNum) {
    *arr = (int**)malloc(sizeof(int*) * rowNum);
    if (*arr == NULL) {
        return;
    }
    for (int i = 0; i < rowNum; i++) {
        (*arr)[i] = (int*)malloc(sizeof(int) * colNum);
        if ((*arr)[i] == NULL) {
            // 回滚已分配的内存
            for (int j = 0; j < i; j++) {
                free((*arr)[j]);
            }
            free(*arr);
            *arr = NULL;
            return;
        }
    }
}

void SetArr(int **arr, int rowNum, int colNum) {
    for (int i = 0; i < rowNum; i++) {
        for (int j = 0; j < colNum; j++) {
            int input;
            scanf_s("%d", &input);
            arr[i][j] = input;
        }
    }
}

额外提醒

  • 内存分配必检查:每次调用malloc后都要判断是否成功,避免后续操作空指针。
  • 及时释放内存:使用完动态分配的内存后一定要逐层释放,防止内存泄漏。
  • 减少全局变量:全局变量会增加代码耦合度,尽量用局部变量和参数传递数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:17:32