c++ - std::string compare() 给出段错误:

标签 c++ string segmentation-fault compare

所以我正在创建一个函数,仅当字符串是尚未包含在 vector 中的唯一字符串时,才会将新字符串添加到字符串 vector 中。这是我的代码:

void CityMapper::addToVector(string& s)
{
    bool newWord = true;
    if(numAirports > 0)
    {
        for(int i = 0; i < numAirports; i++)
        {
            if(airportNames[i].compare(s) == 0)
                newWord = false;
        }
    }
    if(newWord == true)
    {
        airportNames.pushBack(s);
        numAirports++;
    }
}

airportNames 是字符串 vector 。当我运行该程序时,它会在 Valgrind 中出现以下错误:

Process Terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0x0

在此之前,Valgrind 终端中出现此错误:

Invalid Read of Size 8

两者都发生在 string.compare() 行。有谁知道为什么会这样?我也尝试了参数中没有 & 符号的函数。

编辑:我采纳了 Derek 的建议并进行了所有更改。现在程序在我从文件中读取字符串的另一种方法中出现段错误。这是该函数的代码:

void CityMapper::getCities()
{
    ifstream fin;
    fin.open(flightDataFile);
    fin >> numAirports;
    string tempCity1, tempCity2, tossout;
    while(getline(fin, tempCity1, ','))
    {
        fin.ignore(1);
        getline(fin, tempCity2, ',');
        fin.ignore(1);
        getline(fin, tossout, '\n');
        addToVector(tempCity1);
        addToVector(tempCity2);
    }
}

以下是来自 Valgrind 的错误消息:

==8357== Use of uninitialised value of size 8
==8357==    at 0x4EF158B: std::basic_string<char, std::char_traits<char>,     
std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-
gnu/libstdc++.so.6.0.17)
==8357==    by 0x402214: CityMapper::getCities() (in 
/home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==    by 0x401EB7: CityMapper::run() (in /home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==    by 0x4050A0: main (in /home/charlie/NetBeansProjects/Lab4/Lab4)
==8357== 
==8357== Invalid read of size 4
==8357==    at 0x4EF158B: std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-
gnu/libstdc++.so.6.0.17)
==8357==    by 0x402214: CityMapper::getCities() (in   
/home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==    by 0x401EB7: CityMapper::run() (in /home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==    by 0x4050A0: main (in /home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==  Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd
==8357== 
==8357== 
==8357== Process terminating with default action of signal 11 (SIGSEGV)
==8357==  Access not within mapped region at address 0xFFFFFFFFFFFFFFF8
==8357==    at 0x4EF158B: std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-
gnu/libstdc++.so.6.0.17)
==8357==    by 0x402214: CityMapper::getCities() (in 
/home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==    by 0x401EB7: CityMapper::run() (in /home/charlie/NetBeansProjects/Lab4/Lab4)
==8357==    by 0x4050A0: main (in /home/charlie/NetBeansProjects/Lab4/Lab4)

最佳答案

compare 不会导致段错误。这是您尝试在其上调用它的不存在的对象。作为一般规则:永远不要存储冗余信息(在这种情况下为 numAirports)。如果您必须存储冗余信息,您至少应该检查一致性。在您上面发布的代码中,格式错误的输入文件会使您的应用程序崩溃。只需完全删除 numAirports,您不需要它。

改为使用以下内容:

void CityMapper::addUnique( const string& name )
{
    if ( std::find( airportNames.begin(), airportNames.end(), name )
         == airportNames.end() )
    {
        // Name does not yet exist -> add it
        airportNames.push_back( name );
    }
}

注意事项:

  • 该方法已重命名以反射(reflect)其语义。您不应在函数名称( vector )中对数据类型进行编码。
  • 签名已更改为采用const 引用。该方法不会更改此参数,这就是以编译器可以验证的方式记录的方式。
  • 参数名称已更改为名称。毕竟,这就是它所代表的。
  • 循环已替换为库代码 (std::find)。不要试图重新发明轮子。

正如评论中指出的那样,如果没有令人信服的理由使用 std::vector,您应该看看 std::setstd::unordered_set .两个容器都存储唯一对象,因此您不必编写自己的addUnique

关于c++ - std::string compare() 给出段错误:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19640164/

相关文章:

C++ 用单个值填充空缓冲区

c++ - 在什么情况下,单例设计模式可能会生成同一个单例类的多个实例?

c++ - 编码一个句子

string - 测试字符串中的日文/中文字符

c++ - 检查 NULL 时要忽略多少位?

c - 为什么在写入使用字符串文字初始化的 "char *s"而不是 "char s[]"时出现段错误?

c++ - 全局内存写入在 CUDA 中被认为是原子的吗?

c++ - 如何初始化 Matrix<T,Rows,Cols> 类型的 constexpr 矩阵?

java - 如何检查子字符串是否位于字符串末尾

c++ - 树实现给出段错误(核心转储)错误 c++ 11