读取CSV存入map<vector<uint>>结构出现段错误的原因求解
段错误原因分析
- 空指针未校验直接访问
代码未对strtok的返回值做非空校验就直接使用,是触发段错误的核心原因:- 读取每行第一个字段(寄存器名称)后,直接调用
pch = strtok(NULL, DELIMS)获取地址字段,如果该行没有后续的地址内容、或者行格式异常,pch会直接返回NULL,此时执行strtoul(pch,NULL,10)就会触发空指针解引用。 - 内层循环逻辑顺序错误:先执行
pch = strtok(NULL, DELIMS)获取下一个地址字段,没有判断是否为NULL就直接传入strtoul,当所有地址字段处理完毕后,strtok会返回NULL,此时直接访问就会触发段错误。
- 读取每行第一个字段(寄存器名称)后,直接调用
- 首字段未做合法性校验
首次调用strtok(buffer, DELIMS)获取名称字段时,如果当前行是空行、行首为逗号,row会返回NULL,后续执行std::string(row)构造字符串时也会触发空指针访问。
修正后的代码参考
int SomeClass::readCSV(std::string fileName) { const uint MAX_LINE_LENGTH = 1024; const char* DELIMS = ","; // 读文件建议用std::ifstream std::ifstream fin(fileName); if (!fin.is_open()) { spdlog::get("runtime_log")->error("Could not open file {0}.", fileName); return -1; } char buffer[MAX_LINE_LENGTH] = {}; char* pch; std::vector<uint> values; while (fin.getline(buffer, MAX_LINE_LENGTH)){ // 先校验首字段非空 char* row = strtok(buffer, DELIMS); if (row == NULL) { // 空行直接跳过 continue; } values.clear(); // 读取所有地址字段,先判断非空再转换 pch = strtok(NULL, DELIMS); while (pch != NULL) { values.push_back(strtoul(pch, NULL, 10)); pch = strtok(NULL, DELIMS); } // 可加校验:如果values为空可打警告或者跳过 register_map[std::string(row)] = values; } return 1; }
内容的提问来源于stack exchange,提问作者Charkrit_A
相关产品推荐
相关产品推荐

