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

Win32程序调用fscanf导入CSV触发段错误,gdb定位到ungetwc报错

段错误触发原因及解决方法

触发原因

  • 变量拼写错误+未初始化野指针:你定义的FILE指针变量名为sorgente,但实际代码中赋值、操作使用的变量名为source,变量名不匹配,在部分编译环境下会被识别为未定义的野指针。同时即使拼写一致,你将FILE指针定义在switch(msg)块的开头,C语言中switch块的case标签外的变量不会在进入对应case时自动初始化,若fopen返回NULL,后续执行fclose(source)相当于对空指针执行释放操作,直接触发段错误。
  • 读取逻辑错误导致数组越界:你使用!feof(source)作为循环判断条件,feof仅在读取操作失败后才会返回真,该逻辑会导致最后一次读取失败后仍执行i++操作,若CSV文件行数超过1000行,会越界访问全局数组user,触发内存访问错误。
  • 缓冲区无长度限制导致溢出:结构体中name字段仅15字节长度,你使用%[^,]格式符读取字符串时未限制长度,若CSV中name字段长度超过14字节(需留1字节存储字符串终止符\0),会发生缓冲区溢出,破坏内存结构触发段错误。
  • 字符编码不匹配:你使用的窗口过程为宽字符版本DefWindowProcW,若VSCode编译环境默认开启宽字符配置,fscanf处理编码不匹配的CSV文件时会触发内部宽字符处理函数ungetwc报错,就是你gdb调试时看到的错误。

解决方法

  • 修正变量拼写与作用域:将FILE指针定义在IMPORT的case块内部,初始化为NULL,仅当fopen成功时才执行fclose操作:
case IMPORT:{
    int i = 0;
    FILE *source = NULL; // 块内定义并初始化,变量名统一为source
    if ((source = fopen("./Data/users.csv", "r")) == NULL) {
        printf("can't open the file.\n");
    } else {
        // 读取逻辑
        fclose(source); // 仅打开成功时关闭
    }
    break;
}
  • 修正文件读取逻辑:直接用fscanf的返回值作为循环判断条件,同时限制读取行数不超过数组容量,限制字符串读取长度避免溢出:
// 最多读1000条,%14[^,]限制name最长14字节,返回值为4表示4个字段全部读取成功
while(i < 1000 && fscanf(source,"%14[^,],%d,%f,%f\n", user[i].name, &user[i].born, &user[i].price, &user[i].average) == 4) {
    i++;
}
  • 统一字符编码:若CSV文件为UTF-8编码,可在fopen后添加编码声明,或调整编译选项将窗口字符集与文件读取字符集统一,避免宽字符处理错误。
  • 补充边界判断:可在读取完成后添加i的数值打印,确认读取行数是否符合预期,避免异常越界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 13:06:01