【问题标题】:Iterator Segfault with List class in C++C++ 中带有 List 类的迭代器段错误
【发布时间】:2020-06-09 16:34:33
【问题描述】:

我正在为我的一个 comp sci 类开发一个项目,该类使用哈希表将字符串排序为来自 STL 的列表类的链表向量。将字符串插入列表时,除索引 3 之外的所有索引始终会导致 SEGFAULT 错误。我不知道为什么会这样。这是插入函数的代码以及我收到的一些错误示例。在默认构造函数中,向量“table”被声明为包含 4 个元素

void Stringset::insert(string word)
{
    cout << "insertion" << endl;
    hash<string> stringHash;
    int hashIndex = stringHash(word) % size;
    cout << hashIndex << endl;
    bool exists = false;
    //find intended index and create base boolean variable for whether or not the value already exists
    list<string>::iterator pos = table[hashIndex].begin();
    list<string>::iterator end = table[hashIndex].end();
    for(pos; pos != end; pos++){
        cout << "pass" << endl;
        if((*pos).compare(word) == 0){
            exists = true;
        }
    }
    if(!exists){
        table[hashIndex].push_back(word);
        num_elems++;
        cout << "inserted " << (*pos) << endl;
    }
    else{

    }
}

这里有几个 SEGFAULT 发生的例子以及插入的情况,其中 a 为 3 工作:

I: insert word
F: find word
R: remove word
P: print words in stringset
Q: quit
I
Enter word to insert: By
insertion
3
inserted 
I: insert word
F: find word
R: remove word
P: print words in stringset
Q: quit
I
Enter word to insert: Try
insertion
3
pass
inserted 
I: insert word
F: find word
R: remove word
P: print words in stringset
Q: quit
I
Enter word to insert: Error
insertion
2
Segmentation fault (core dumped)

加上单数:

I: insert word
F: find word
R: remove word
P: print words in stringset
Q: quit
I
Enter word to insert: Error
insertion
2
Segmentation fault (core dumped)

Stringset.h 以及 Stringset 对象的默认构造函数:

#pragma once

#include <string>
#include <vector>
#include <list>
using namespace std;

//Stringset class, do not modify definitions for existing members
class Stringset
{
    private:
        vector<list<string>> table;
        int num_elems;
        int size;
    public:
        Stringset();
        vector<list<string>> getTable() const;
        int getNumElems() const;
        int getSize() const;
        void insert(string word);
        bool find(string word) const;
        void remove(string word);
};

Stringset::Stringset() : table(4), num_elems(0), size(4) {}

我相当肯定,一旦程序遇到 for 循环,它总是会崩溃,但由于我不熟悉迭代器,我不确定为什么。任何有关如何解决此问题的想法将不胜感激。

【问题讨论】:

  • table 是如何定义和填充的,sizetable 的关系是什么?为什么不改用table.size()
  • 你能展示你的构造函数吗?更具体地说,你能说明table 是如何初始化的吗?您是否为表向量的所有索引创建列表对象?您的示例表明只有最后一个条目被正确初始化,而其他条目要么未初始化要么为空。我怀疑你的错误在你的构造函数中
  • tangent: cout &lt;&lt; "inserted " &lt;&lt; (*pos) &lt;&lt; endl; 书面取消引用结束迭代器。您可能打算写 word 而不是 *pos。找到匹配的单词后,您可以break 退出搜索循环。
  • @John "您可以在找到匹配的单词后将break 退出搜索循环'- 或者,更好的是,考虑使用std::find_if() 而不是手册循环:if (find_if(table[hashIndex].begin(), table[hashIndex].end(), [&amp;](string &amp;s){ return s.compare(word) == 0; }) == table[hashIndex].end()) { ... }
  • @Remy 停止编辑你的评论,这样我就不必继续重新投票了。

标签: c++ string list hashtable


【解决方案1】:

你的代码基本正确。

错误在您的cout &lt;&lt; "insert" ... 行中。 正如 cmets 中已经指出的那样,(*pos) 指向endl,当您到达该代码行时,该代码行“超出”列表。这意味着它不再指向有效的对象。这会导致段错误。

如果我注释掉那一行,它对我有用。

ps - 我在上面的评论中的怀疑是错误的。你的构造函数是正确的:-)

【讨论】:

    【解决方案2】:

    我会仔细检查 hashIndex 计算。这可能会导致 SEGFAULT。您也可以使用一些 c++ 语法来避免一些头痛。看看下面的变化:

    //list<string>::iterator pos = table[hashIndex].begin();
    //list<string>::iterator end = table[hashIndex].end();
    bool exists = false;
    for (auto& Pos : table[hashIndex]) {
        cout << "pass" << endl;
        if (Pos.compare(word) == 0) {
           exists = true;
           break;
        }
    }
    if (!exists) {
       table[hashIndex].push_back(word);
       num_elems++;
       //cout << "inserted " << (*pos) << endl;   
       //Pos was pointing to the .end() in your coude
       cout << "inserted " << table[hashIndex].back() << endl;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-29
      • 1970-01-01
      • 2018-03-23
      • 2017-10-10
      • 1970-01-01
      • 2019-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多