C++实现第三新日期查找在HackerRank报SIGSEGV段错误求助
C++实现第三新日期查找触发段错误问题排查
问题背景
- 此前放弃Java实现方案,改用C++重写第三新日期查找功能,本地编译器测试运行正常,提交到HackerRank平台时持续抛出Segmentation fault段错误。
- 已知段错误一般由非法内存访问引发,自查代码5小时未定位问题点。
附:问题完整代码
struct Date { int Day; int Year; int Month; bool latest(Date d){ if (Year > d.Year){ return true; } else if (Year == d.Year) { if(Month > d.Month){ return true; } else if (Month == d.Month){ if(Day> d.Day){ return true; } } } } }; Date ThirdLatest(std::vector<Date> &dates) { vector<Date> d; int length = dates.size(); //std::cout << std::unitbuf; for (int i=0; i<length; i++){ int flag = 0; for (int j=0; j<d.size(); j++){ if (dates[i].Day == d[j].Day && dates[i].Month == d[j].Month && dates[i].Year == d[j].Year){ flag = 1; break; } } if (flag ==1) d.push_back(dates[i]); } Date temp; for (int i=0; i<d.size(); i++){ for (int j=i+1; j<d.size(); j++){ if (!d[i].latest(d[j])){ temp.Day = d[i].Day; temp.Month = d[i].Month; temp.Year = d[i].Year; d[i].Day = d[j].Day; d[i].Month = d[j].Month; d[i].Year = d[j].Year; d[j].Day = temp.Day; d[j].Month = temp.Month; d[j].Year = temp.Year; } } } return d[2]; } int main() { int numberOfEntries; int res = scanf("%d\n", &numberOfEntries); std::vector<Date> dates; for (int i = 0; i < numberOfEntries; ++i) { Date date; res = scanf("%d-%d-%d", &date.Day, &date.Month, &date.Year); dates.push_back(date); } Date result = ThirdLatest(dates); printf("%02d-%02d-%d\n", result.Day, result.Month, result.Year); return 0; }
编译器报错输出
Reading symbols from Solution...done. [New LWP 71078] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Core was generated by `./Solution'. Program terminated with signal SIGSEGV, Segmentation fault. #0 ThirdLatest (dates=...) at Solution.cpp:57 57 for (int i=0; i<length; i++){ To enable execution of this file add add-auto-load-safe-path /usr/local/lib64/libstdc++.so.6.0.25-gdb.py line to your configuration file "//.gdbinit". To completely disable this security protection add set auto-load safe-path / line to your configuration file "//.gdbinit". For more information about this security protection see the "Auto-loading safe path" section in the GDB manual. E.g., run from the shell: info "(gdb)Auto-loading safe path"
测试样例
输入
7 14-04-2001 29-12-2061 21-10-2019 07-01-1973 19-07-2014 11-03-1992 21-10-2019
预期输出
19-07-2014
问题根因与修复方法
代码存在两个明确bug,其中第一个直接触发段错误:
- 去重逻辑写反,导致数组越界
去重环节的判断条件完全写反:当前逻辑是if (flag ==1) d.push_back(dates[i]),也就是只有发现日期重复时才把元素加入去重数组d。但初始状态下d是空数组,遍历所有日期时内层查重循环根本不会触发,flag始终为0,没有任何元素会被加入d,最终执行return d[2]时访问了空数组的非法内存,直接触发段错误。本地测试未崩溃是因为本地编译选项未开启严格的内存检查,栈内存残留值刚好让程序没触发崩溃,但输出结果本身就是错误的。
修复:把判断条件改成if (flag == 0),即查重没发现重复时,才把当前日期加入d。 - 比较函数缺失返回值,触发未定义行为
latest函数只在“当前日期晚于传入日期”时返回true,所有相等、更早的分支都没有写return false,函数返回值是栈上的随机垃圾值,会直接导致后续排序逻辑混乱,就算不触发段错误也会得到错误结果。
修复:在latest函数所有比较逻辑的末尾加return false;,补全所有分支的返回值。
改完这两点后跑样例:去重后得到6个不重复日期,降序排序后下标0是最晚的2061-12-29,下标1是2019-10-21,下标2就是2014-07-19,完全符合预期输出。
内容的提问来源于stack exchange,提问作者Safwan Parkar
相关产品推荐
相关产品推荐

