C++ C++;传递向量<;字符串>;元素运行会导致SIGSEGV崩溃

C++ C++;传递向量<;字符串>;元素运行会导致SIGSEGV崩溃,c++,string,vector,segmentation-fault,function-call,C++,String,Vector,Segmentation Fault,Function Call,问题是,正如标题所说,当我试图将第二个向量元素传递给函数“solveSide”时,这个向量包含两个字符串标记,它们是从一个更大的字符串和一个用户定义的函数中获得的 该程序的工作原理如下: 将文件中的行读入字符串 调用“stringSplit”函数从该行字符串中获取两个标记,并将它们放入向量中 为向量中的第一个元素调用“solveSide” 为向量中的第二个元素调用“solveSide” 问题出现在对“solveSide”的第二次调用中,因为程序在进入函数体之前崩溃 如果我删除对“solveS

问题是,正如标题所说,当我试图将第二个向量元素传递给函数“solveSide”时,这个向量包含两个字符串标记,它们是从一个更大的字符串和一个用户定义的函数中获得的

该程序的工作原理如下:

  • 将文件中的行读入字符串
  • 调用“stringSplit”函数从该行字符串中获取两个标记,并将它们放入向量中
  • 为向量中的第一个元素调用“solveSide”
  • 为向量中的第二个元素调用“solveSide”
问题出现在对“solveSide”的第二次调用中,因为程序在进入函数体之前崩溃

如果我删除对“solveSide”函数的第二个调用,程序运行正常。 如果我试图在不删除该行的情况下输出向量的两个元素,它不会输出任何内容,但删除后,它会输出两个元素

在调试模式下,当调用“std::string::_M_mutate(unsigned int,unsigned int,unsigned int)”(如调用堆栈所示)时,它抛出SIGSEGV

崩溃代码:

ifstream fin("ecuatii.in");
string ecuatie;
vector<string> sideSplit;

fin>>ecuatie;
sideSplit = stringSplit(ecuatie, "=");
fout<<sideSplit[0]<<"="<<sideSplit[1]<<"\n";
solveSide(sideSplit[0], leftCoeffSum, leftSum);
solveSide(sideSplit[1], rightCoeffSum, rightSum);

输入字符串:
2.0x-4+5x+300=98x

此块不仅没有必要,而且为您带来了未定义行为的乐趣:

for(unsigned i = 0; i < tokenCount; ++i){
     delete[] tokens[i];
}

这一块不仅没有必要,而且给您带来了未定义行为的乐趣:

for(unsigned i = 0; i < tokenCount; ++i){
     delete[] tokens[i];
}

使用vector更安全的方法是使用splits.pushback()方法,而size作为spits.size()更安全。在分配给vector的成员之前,始终检查vector.size()。

使用vector更安全的方法是使用splits.pushback()方法和size更安全地获得spits.size()。在分配给vector成员之前,始终检查vector.size()。

我发现了问题,这更像是一个思维错误:

当使用第二个字符串作为参数调用函数
solveSide
时,该函数的值为
98x
,它在搜索
startPos=npos
后搜索
“+”
“-”
符号,因为它找不到它,并且它在
while
之前输入这种情况:

}else{
    currentNumber = stringChunkToFloat(side, 0, posStart-1);
    sum += currentNumber;
}

当它试图从位置
0
npos
获取数字时,它抛出SIGSEGV(分段错误),因为它试图从传递到
stringChunkToFloat

的字符串中访问未分配的内存。我发现了这个问题,这更像是一个思维错误:

当使用第二个字符串作为参数调用函数
solveSide
时,该函数的值为
98x
,它在搜索
startPos=npos
后搜索
“+”
“-”
符号,因为它找不到它,并且它在
while
之前输入这种情况:

}else{
    currentNumber = stringChunkToFloat(side, 0, posStart-1);
    sum += currentNumber;
}


当它试图从位置
0
npos
获取数字时,它抛出SIGSEGV(分段故障),因为它试图从传递到
stringChunkToFloat

的字符串中访问未分配的内存,所以请使用调试器,将问题缩小到特定的代码行/序列。我这样做了,执行正好在第二次调用“solveSide”的行停止是制作的。@user2327048:is
stringChunkToFloat
基本上是
substr()
然后是
atof
?@Zeta我在问题中添加了这个函数(够尴尬的,它不是substr()),我刚刚开始学习如何使用STL,因此,我有很多漏洞。请使用调试器并将问题缩小到特定的代码行/序列。我这样做了,并且执行正好在第二次调用“solveSide”的行停止。@user2327048:is
stringChunkToFloat
基本上
substr()
之后是
atof
?@Zeta我在问题中添加了这个函数(很尴尬,它不是substr()),我刚刚开始学习如何使用STL,所以我有很多差距。“给你带来了未定义行为的乐趣”,也许我很愚蠢,但对此我笑了很多。很好的回答,+1:)你是对的,因为我已经删除了“strCopy”,这样做没有意义,即使我没有删除,我也认为在第一个令牌[I]删除后,行为将是未定义的。无论如何,这似乎不是SIGSEGV问题的原因(或者至少不是唯一的原因)@user2327048:在这种情况下,我们需要
solveSide
函数和您的输入字符串。您是否打印了
ecuatie
并检查了分割向量的大小?@CantChooseServerNames:Typo,意思是
tokens
,而不是
token
“给您带来了未定义行为的乐趣”,也许我很愚蠢,但对此我笑了很多。很好的回答,+1:)你是对的,因为我已经删除了“strCopy”,这样做没有意义,即使我没有删除,我也认为在第一个令牌[I]删除后,行为将是未定义的。无论如何,这似乎不是SIGSEGV问题的原因(或者至少不是唯一的原因)@user2327048:在这种情况下,我们需要
solveSide
函数和您的输入字符串。您是否打印了
ecuatie
并检查了分割向量的大小?@CantChooseServerNames:Typo,意思是
标记
,而不是
标记
vector<string> stringSplit(const string& str, const char *delim){
    // Note: if you use C++11, you can use std::string::data() 
    // and don't need a copy to a vector, just take the string by value
    vector<char> strCopy(str.begin(), str.end());
    strCopy.push_back('\0');

    vector<char*> tokens;
    {        
        char * token = strtok(strCopy.data(), delim);
        while(token != NULL){
            tokens.push_back(token);
            token = strtok(NULL, delim);
        }
    }

    vector<string> splits(tokens.size();
    for(unsigned i = 0; i < tokens.size(); ++i){
         splits[i] = "";
         splits[i] += tokens[i];
    }

    return splits;
}
}else{
    currentNumber = stringChunkToFloat(side, 0, posStart-1);
    sum += currentNumber;
}