Visual Studio 2019运行C语言代码时SetArr函数触发Access violation错误求助
解决Access Violation错误的分析与修正
先直接点出核心问题:你的代码触发访问冲突的根源是全局指针arr1根本没被正确初始化,再加上函数参数传递的逻辑错误,导致程序试图访问非法的内存地址。
具体问题拆解
传值调用的陷阱
你的zeros函数接收的是int** arr参数,这是典型的传值调用——函数内部修改的只是这个参数的副本,完全不会影响外部的全局变量arr1。调用zeros(arr1, 2, 3)后,arr1仍然是一个未初始化的野指针,后续在SetArr里访问arr1[i][j]必然会触发访问冲突。函数内误用全局变量
SetArr函数明明接收了arr参数,但你却在函数里直接操作全局的arr1,这不仅违背了函数设计的初衷,还让指针问题变得更严重。全局循环变量的潜在风险
你用了全局的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
相关产品推荐
相关产品推荐

