C++代码运行触发Segmentation fault (core dumped),求排查代码问题
代码段错误问题排查
问题描述
输入字符串unsophisticated后,程序触发Segmentation fault (core dumped),需定位代码中的问题。
原代码
string s; cin>>s; s[0]=s[0]-32; replace(s.begin(),s.end(),'s','$'); replace(s.begin(),s.end(),'i','!'); replace(s.begin(),s.end(),'o','('); for (auto i = s.begin(); i != s.end(); ++i) { if (*i == '(') { s.insert(i + 1, ')'); } } s+="."; cout<<s<<endl;
编译运行结果
cd "/home/parvez/Documents/cds/" && g++ Better_Passwords.cpp -o Better_Passwords && "/home/parvez/Documents/cds/"Better_Passwords unsophisticated Segmentation fault (core dumped)
问题根源
核心问题是遍历字符串时执行插入操作导致迭代器失效:
- 当调用
s.insert(i + 1, ')')时,std::string的内部存储可能会重新分配内存或调整元素位置,此时原迭代器i会直接失效。 - 后续循环中继续使用失效的迭代器执行
++i,会访问非法内存,触发段错误。 - 即使没有触发内存重新分配,插入操作会让
i之后的元素全部后移一位,循环会跳过下一个字符,同时字符串长度持续增加,导致循环条件i != s.end()永远无法满足,最终因越界访问崩溃。
以输入unsophisticated为例,替换后字符串包含多个(,每次插入)都会导致迭代器失效,后续操作必然出错。
修复方案
提供两种可靠的修复方式:
方式1:使用索引遍历(规避迭代器失效问题)
string s; cin>>s; // 先判断字符串非空,避免访问空字符串的首元素 if (!s.empty()) { s[0] = s[0] - 32; } replace(s.begin(), s.end(), 's', '$'); replace(s.begin(), s.end(), 'i', '!'); replace(s.begin(), s.end(), 'o', '('); // 用索引遍历,插入后调整索引跳过新元素 for (size_t i = 0; i < s.size(); ++i) { if (s[i] == '(') { s.insert(i + 1, ')'); ++i; // 跳过刚插入的')',避免重复处理 } } s += "."; cout << s << endl;
方式2:利用insert返回的有效迭代器更新遍历位置
string s; cin>>s; if (!s.empty()) { s[0] = s[0] - 32; } replace(s.begin(), s.end(), 's', '$'); replace(s.begin(), s.end(), 'i', '!'); replace(s.begin(), s.end(), 'o', '('); auto i = s.begin(); while (i != s.end()) { if (*i == '(') { // insert返回指向新插入字符的迭代器,更新后跳过该字符 i = s.insert(i + 1, ')'); ++i; } else { ++i; } } s += "."; cout << s << endl;
两种方案都解决了迭代器失效的问题,同时新增了空字符串判断,避免潜在的越界访问风险。
内容的提问来源于stack exchange,提问作者Parvez Ali
相关产品推荐
相关产品推荐

