调用printRoot函数触发ucrtbased.dll访问违例错误排查
我定义了以下结构体及指针类型:
struct tree { itemType name[MAX]; struct tree* left; struct tree* right; }; typedef struct tree* treenode;
同时编写了printRoot函数用于打印结构体数组中的名称:
void printRoot(treenode root[]){ int i = 0; while (root[i] != NULL) { printf("\n\t\t%c %s", 254, root[i]->name); i++; } }
调用该函数时程序终止并抛出错误:
Exception thrown at 0x00007FFC0DCC2487 (ucrtbased.dll) 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
同时自动打开了stdio.h文件。
直接访问单个数组元素(比如printf("%s", ROOT[0]->name);)时程序运行正常,因此问题应该出在printRoot函数的遍历逻辑中,但无法定位具体原因。
补充说明
这是一个模拟文件管理器的课程项目,设计思路是用结构体指针数组存储多棵二叉搜索树,项目分为main、implementation、header三个文件,相关未完成代码如下:
main文件代码:
#include "Header.h" int main() { treenode ROOT[50]; char choice; printf("\n\t\tDo you want to create a folder? [Y/N]: "); scanf("%c", &choice); choice = tolower(choice); if (choice == 'y') { itemType folname[MAX]; printf("\n\t\tEnter folder name: "); scanf(" %s", folname); ROOT[0] = createFolder(folname); printf("%s", ROOT[0]->name); // 此代码正常运行 //printRoot(ROOT); --> 待修复的问题代码 } else { printf("\ntest"); } }
implementation文件代码:
treenode createFolder(itemType x[]) { treenode touch = (struct tree*)malloc(sizeof(struct tree)); strcpy(touch->name, x); touch->left = NULL; touch->right = NULL; return touch; } void printRoot(treenode root[]){ int i = 0; while (root[i] != 0) { printf("\n\t\t%c %s", 254, root[i]->name); i++; } }
问题原因与解决方案
原因分析
局部数组ROOT[50]未初始化,C语言中局部变量默认不会自动初始化为NULL或0。你只给ROOT[0]赋值了有效的指针,而数组中其他元素都是随机的垃圾值(可能是类似0xFFFFFFFFFFFFFFFF的非法地址)。printRoot函数的循环条件root[i] != NULL会一直遍历,直到访问到非法内存区域,触发访问违例错误。
修复方案
初始化数组为NULL:
定义数组时直接初始化所有元素为NULL,这样未被赋值的元素都会是NULL,循环会在遇到第一个NULL时停止:treenode ROOT[50] = {NULL};(注:C语言中数组初始化时,未显式赋值的元素会自动被初始化为0/NULL)
维护元素计数器:
额外定义一个变量记录数组中已创建的文件夹数量,遍历到该数量时停止循环。比如在main中添加int folderCount = 0;,创建文件夹后folderCount++;,修改printRoot函数接收计数器参数:void printRoot(treenode root[], int count){ int i = 0; while (i < count) { printf("\n\t\t%c %s", 254, root[i]->name); i++; } }调用时传参:
printRoot(ROOT, folderCount);
内容的提问来源于stack exchange,提问作者lectheeth

