std :: string compare()给出分段错误:

pri*_*int 0 c++ string compare segmentation-fault

所以我正在创建一个函数,只要字符串是一个尚未包含在向量中的唯一字符串,它就会向字符串向量添加一个新字符串.这是我的代码:

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++;
    }
}
Run Code Online (Sandbox Code Playgroud)

airportNames是字符串的向量.当我运行程序时,它会在Valgrind中出现以下错误:

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

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

Invalid Read of Size 8
Run Code Online (Sandbox Code Playgroud)

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

编辑:我接受了德里克的建议,并完成了所有的改变.现在程序是以不同的方法进行分区,我从文件中读取字符串.这是该函数的代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是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)
Run Code Online (Sandbox Code Playgroud)

IIn*_*ble 6

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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 该方法已重命名以反映其语义.您不应该在函数名称(向量)中编码数据类型.
  • 签名已更改为const参考.该方法不会改变此参数,这就是编译器可以验证的方式.
  • 参数名称已更改为name.毕竟,这就是它所代表的.
  • 循环已替换为库代码(std::find).不要试图重新发明轮子.

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

  • 很好的答案.IMO这个问题确实值得提到`std :: set`(比如@JerryCoffin的评论). (3认同)