程序可写入文本文件但读取时触发访问违例错误,求助排查
解决fscanf_s读取文件时的访问违例(Access Violation)问题
嘿,我看你遇到了fscanf_s读取文件时的访问违例问题——写入正常但读取直接崩了,错误指向stdio.h的第1092行,这个问题大概率和参数传递、内存初始化或者格式匹配有关,咱们一步步来捋清楚:
可能的问题根源
- fscanf_s参数不完整:fscanf_s是微软的安全版本scanf,对于
%s格式符,必须额外传入缓冲区的大小作为参数。你代码里写的MAX_STRING_LEN - ...看起来没写完,如果这里参数缺失或者数值错误,fscanf_s会不知道缓冲区的边界,直接越界写入内存,触发访问违例。 - Product结构体的name成员未正确初始化:如果你的
Product结构体里name是char*类型(而非固定大小的char数组),那局部变量temp的name会是一个野指针,直接用%s写入会导致非法内存访问。 - 读写格式不匹配:如果写入文件时的格式和读取时的fscanf_s格式字符串不对应(比如顺序错了、空格处理不对),会导致解析过程中错误地写入内存区域,引发崩溃。
具体解决方案
补全fscanf_s的参数
对于%s,必须传入缓冲区的大小,正确的写法应该是这样的:// 如果temp.name是固定数组,用_countof获取大小更安全 int moreData = fscanf_s(stream, "%s", temp.name, (unsigned)_countof(temp.name)); // 或者用你定义的MAX_STRING_LEN(确保数组大小和这个宏一致) int moreData = fscanf_s(stream, "%s", temp.name, (unsigned)MAX_STRING_LEN);注意这里的大小参数要传无符号整数,别漏了。
确认Product结构体的定义
确保name是固定大小的char数组,比如:#define MAX_STRING_LEN 256 typedef struct { char name[MAX_STRING_LEN]; // 这里是数组,不是指针! char type; double price; int qty; } Product;如果非要用
char*,那读取前必须先给temp.name分配足够的内存(比如temp.name = malloc(MAX_STRING_LEN);),用完记得释放。严格匹配读写的格式字符串
比如写入时你用的是:fprintf(stream, "%s %c %.2lf %d\n", prod.name, prod.type, prod.price, prod.qty);那读取时的fscanf_s必须对应相同的格式,还要注意
%c的空白问题——前面的%s会跳过空白,但%c会读取任何字符(包括空格、换行),所以最好在%c前加个空格跳过空白:int moreData = fscanf_s(stream, "%s %c %lf %d", temp.name, (unsigned)_countof(temp.name), &temp.type, &temp.price, &temp.qty);另外,要检查返回值
moreData,如果不等于你要读取的参数个数(这里是4),说明格式不匹配或者文件读取到末尾了。检查文件流的状态
写完文件后一定要fclose,然后再重新打开读取;如果是同一个流读写,记得用fseek(stream, 0, SEEK_SET)把文件指针移回开头,不然会从文件末尾开始读,导致错误。
完整示例代码
这里给你一个能正常读写的小例子,参考一下:
#include <stdio.h> #include <stdlib.h> #define MAX_STRING_LEN 256 typedef struct { char name[MAX_STRING_LEN]; char type; double price; int qty; } Product; // 写入产品到文件 void writeProduct(FILE* stream) { Product sample = {"Orange", 'F', 2.49, 80}; fprintf(stream, "%s %c %.2lf %d\n", sample.name, sample.type, sample.price, sample.qty); } // 从文件读取产品 int readProduct(FILE* stream) { Product temp; int readCount = fscanf_s(stream, "%s %c %lf %d", temp.name, (unsigned)_countof(temp.name), &temp.type, &temp.price, &temp.qty); if (readCount == 4) { printf("读取成功:%s | %c | %.2lf | %d\n", temp.name, temp.type, temp.price, temp.qty); return 1; } else if (readCount != EOF) { printf("格式不匹配或部分读取\n"); return 0; } return 0; } int main() { FILE* fp; // 写入文件 if (fopen_s(&fp, "products.txt", "w") != 0) { printf("打开文件写入失败\n"); return 1; } writeProduct(fp); fclose(fp); // 读取文件 if (fopen_s(&fp, "products.txt", "r") != 0) { printf("打开文件读取失败\n"); return 1; } while (readProduct(fp)); fclose(fp); return 0; }
内容的提问来源于stack exchange,提问作者Frank Gatto
相关产品推荐
相关产品推荐

