比较int时触发Read access violation问题排查求助
Read Access Violation 问题诊断与修复
你的代码中触发Read Access Violation的核心原因是二叉树和链表的根指针初始化错误,导致insert函数访问了未初始化的垃圾内存。以下是具体分析和修复方案:
核心错误点
二叉树根指针初始化错误
在main函数中,你用struct treeNode *tree = malloc(size * sizeof(struct treeNode));分配了一块内存,但二叉树的根指针应该初始化为NULL——insert函数的逻辑是当node == NULL时创建新节点,而malloc返回的未初始化内存不是NULL,导致insert进入非空分支时,node指向无效内存,访问node->num直接触发读访问违规。链表头指针初始化错误
同理,struct listNode *list = malloc(size * sizeof(struct listNode));也是错误的,链表头指针必须初始化为NULL,否则newNode函数在更新链表时会操作垃圾内存,引发后续访问错误。
次要问题(需同步修复)
LOAD函数中用atol(tmp)将字符串转为long,但insert的参数是int,可能导致整数溢出,建议改用atoi(tmp)。SCAN和LOAD中分配的字符数组未释放,存在内存泄漏。printList函数循环条件错误:若链表为空,tmp->next会触发空指针访问;且当前逻辑会跳过第一个节点,应改为while (tmp != NULL)。main函数的参数名写反了:标准写法是int argc, char *argv[],你写成了int argv, char *argc[],虽然不影响运行,但不符合规范。- 缺少内存分配和文件打开的错误检查,容易忽略潜在问题。
修复后的完整代码
// Garrett Manley // delete these when turning it in #pragma warning(disable : 4996) #include <stdio.h> #include <stdlib.h> #include <string.h> // define structs struct treeNode { int num; struct treeNode *right, *left; }; struct listNode { struct treeNode *tNode; // data is a pointer to the tree struct listNode *next; }; // creates and returns a new node with given data, also adds node to linked list struct treeNode *newNode(int data, struct listNode **list) { // make tree node struct treeNode *node = malloc(sizeof(struct treeNode)); if (!node) { perror("malloc treeNode failed"); exit(EXIT_FAILURE); } node->num = data; node->left = NULL; node->right = NULL; // make list node struct listNode *newListNode = malloc(sizeof(struct listNode)); if (!newListNode) { perror("malloc listNode failed"); free(node); exit(EXIT_FAILURE); } newListNode->tNode = node; newListNode->next = *list; *list = newListNode; return node; } // inserts given node into the tree in sorted order struct treeNode *insert(struct treeNode *node, int data, struct listNode **list) { if (node == NULL) { // if the tree is empty return new node return newNode(data, list); } else { // if there is a node use recursion to get to the bottom of the tree and add a node in the right spot if (data <= node->num) { node->left = insert(node->left, data, list); } else { node->right = insert(node->right, data, list); } return node; // return the (unchanged) node pointer } } // print linked list void printList(struct listNode *list) { struct listNode *tmp = list; while (tmp != NULL) { printf("%d ", tmp->tNode->num); tmp = tmp->next; } printf("\n"); } // skim through the file and find how many entries there are int SCAN(FILE *stream) { int size = 0; char *str = malloc(100 * sizeof(char)); if (!str) { perror("malloc str failed"); exit(EXIT_FAILURE); } while (fgets(str, 100, stream) != NULL) { // 去除换行符并跳过空行 str[strcspn(str, "\n")] = '\0'; if (strlen(str) > 0) { size++; } } free(str); return size; } // loop through the file and load the entries into the main data array void LOAD(FILE *stream, int size, struct treeNode **tree, struct listNode **list) { rewind(stream); char *tmp = malloc(100 * sizeof(char)); if (!tmp) { perror("malloc tmp failed"); exit(EXIT_FAILURE); } int count = 0; while (count < size && fgets(tmp, 100, stream) != NULL) { str[strcspn(tmp, "\n")] = '\0'; if (strlen(tmp) == 0) continue; *tree = insert(*tree, atoi(tmp), list); count++; } free(tmp); } // 递归释放二叉树节点 void freeTree(struct treeNode *node) { if (node == NULL) return; freeTree(node->left); freeTree(node->right); free(node); } // 释放链表节点 void freeList(struct listNode *list) { struct listNode *tmp; while (list != NULL) { tmp = list; list = list->next; free(tmp); } } // free up everything void FREE(struct treeNode *tree, struct listNode *list) { freeList(list); freeTree(tree); } int main(int argc, char *argv[]) { FILE *file = fopen("./hw7.data", "r"); if (!file) { perror("Failed to open hw7.data"); exit(EXIT_FAILURE); } int size = SCAN(file); struct treeNode *tree = NULL; struct listNode *list = NULL; LOAD(file, size, &tree, &list); // print linked list printList(list); FREE(tree, list); fclose(file); return 0; }
关键修复说明
- 将
tree和list初始化为NULL,符合insert和newNode的逻辑预期。 - 增加了
malloc、fopen的错误检查,避免静默失败。 - 修正了
main函数的参数名,符合C语言规范。 - 实现了
freeTree和freeList函数,避免内存泄漏。 - 处理文件输入时跳过空行,避免无效数据转换。
内容的提问来源于stack exchange,提问作者FunkyMunky
相关产品推荐
相关产品推荐

