在某些循环内使用vector.push_back时出现分段错误
Segmentation fault when using vector.push_back inside of certain loops
根据教授的要求,我目前正在Cygwin终端上使用g++。
我应该取一个输入文件,逐字逐句地阅读,然后将所有单词放在一个向量中,按字母顺序排序,没有重复。
然而,每次我试图在某些循环内操作向量(即-push_back(时,我的程序都会出现分段错误。
以下是我的代码片段:
void word_count(ifstream& input){
string temp;
vector<string> v;
input >> temp; //set first variable
v.push_back(temp);
while (!input.eof()) { //I'm aware of the limitations while using !eof, this is just the way I am required to loop over a file
input >> temp;
for (vector<string>::iterator i = v.begin(); i != v.end(); i++) { //check entire vector for word
if (*i == temp) { //just break and skip the word if it already exists
break;
}
if (i == v.end() - 1) { //if the word doesn't exist yet
for (vector<string>::iterator k = v.begin(); k != v.end(); k++) { //re-search the vector for the proper place
if (k == v.end() - 1) { //if at the end, just push_back the vector
v.push_back(temp); //Causes segmentation fault
break;
}
if ((*k < temp) && (*(k + 1) > temp)) { //find correct place and insert the word in the vector
v.insert(k, temp); //Also causes segmentation fault if execution even manages to get this far
}
}
}
}
}
}
第5行的第一个push_back非常好,我可以多次复制和粘贴它而不会出错。我还可以在输入>>temp(while循环内部(之后立即进行push_back,而不会出现错误。然而,如果我在"k"循环下尝试push_back,它会出现分段错误。我完全被难住了。
我试着在StackOverflow上查看了其他与向量相关的问题,但我真的不明白为什么我可以(或不能(在某些地方使用push_back。
感谢您提前提供的帮助!
编辑1:我应该提到我在VS 2019中测试过它。矢量库文件弹出,说明引发了"读取访问冲突"异常。没有分段故障(或者这可能是VS告诉我发生了分段故障的方式?(
编辑2:修改向量会使迭代器无效。我不知道,谢谢大家的帮助!
编辑3:我只允许使用向量,不允许使用集合或其他容器。如果我能用一套,我会的。
当您修改向量迭代器时,它将无效。
原因有两个:
- 当
push_back
和std::vector::capacity被破坏时,会分配新的块数据,并将数据移动/复制到新的缓冲区 - 当您在中间添加/删除项时,旧迭代器可能会指向可能不再存在的不同项
有一种快速的方法可以修复它。当你进行修改时,你必须获取迭代器的更新值。poush_back
没有这样的功能,但std::vector::insert将迭代器返回到新值,该迭代器可以用于更新循环迭代器。
我可以修复你的代码,但它太复杂了(缩进太多(,我希望避免这种情况。您应该首先将此代码分割为较小的函数。
相反,挽救你的代码,这是我的版本:
template<typename Iter>
size_t count_unique_items(Iter begin, Iter end)
{
using value_type = typename std::iterator_traits<Iter >::value_type;
std::unordered_set<value_type> unique_items;
std::copy(begin, end, std::inserter(unique_items, unique_items.end()));
return unique_itmes.size();
}
size_t count_unique_words(std::istream& input)
{
return count_unique_items(std::istream_iterator<std::string>{input}, {});
}
https://wandbox.org/permlink/bHji7JZoB7E9ZoLn
在迭代向量时修改它可能会使迭代器失效,然后任何事情都可能发生。
但你做得太复杂了——因为向量是有序的,你不需要先看看字符串是否存在,然后搜索正确的位置,你可以直接寻找位置
(你不需要搜索两次,这是你在这个练习中应该做出的发现之一。(
我会(因为你可能不应该使用<algorithm>
的任何功能或类似的"高级"功能(
- 当你到达终点时打破循环或当你找到物品时
- 如果发现一个元素大于该项,则应在该位置之前插入并停止
幸运的是,insert
之前需要插入迭代器,所以您可以使用i
类似这样的东西:
for (vector<string>::iterator i = v.begin(); i != v.end() && *i != temp; ++i)
{
if (*i > temp)
{
v.insert(i, temp);
break;
}
}
注意,break
意味着i
不用于insert
之后的任何比较,因此插入是安全的。
如前所述,您可以使用std::set
来存储您的唯一单词。你可以这样填充它:
std::set<std::string> set_of_words(std::ifstream & input)
{
std::set<std::string> words;
std::string word;
while (input >> word)
{
words.insert(word);
}
return words;
}
或者你可以像你的问题一样使用std::vector
。使用<algorithm>
中的std::lower_bound
,您可以这样使用它:
std::vector<std::string> vector_of_words(std::ifstream & input)
{
std::vector<std::string> words;
std::string word;
while (input >> word)
{
auto pos = std::lower_bound(words.begin(), words.end(), word);
if (pos == words.end())
{
words.push_back(word);
}
else
{
if (*pos != word)
{
words.insert(pos, word);
}
}
}
return words;
}
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 在某些循环内使用vector.push_back时出现分段错误
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 线路抑制状态错误 C4703 可能未初始化的局部指针变量"back"已使用
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误