打印出std :: string崩溃,出现分段错误

时间:2015-03-22 16:17:01

标签: c++ stdstring

我试图在How to cut the content of a string till a particular string or position?改进我对其他问题的回复,以使用指针算法和std::substr,所以我最终得到了以下内容

#include <iostream>
#include <string>
#include <cstring>

std::string getString(std::string fullString){
    char string[80];
    char* endString;
    strcpy(string, fullString.c_str());
    strtok(string, "|");
    for(int i = 0; i < 4; i++){
        endString = strtok(NULL, "|");
    }
    return fullString.substr(endString - string, std::string::npos);
}
int main( void ){
    std::string str("{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread|./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....");
    std::cout << getString(str) << std::endl;
    return 0;
}

然而,如果我将其更改为

,则会因分段错误错误而崩溃
#include <iostream>
#include <string>
#include <cstring>

std::string getString(std::string fullString){
    char string[80];
    char* endString;
    strcpy(string, fullString.c_str());
    strtok(string, "|");
    for(int i = 0; i < 4; i++){
        endString = strtok(NULL, "|");
    }
    std::cout << fullString.substr(endString - string, std::string::npos) << std::endl;
    return fullString.substr(endString - string, std::string::npos);
}
int main( void ){
    std::string str("{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread|./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....");
    std::cout << getString(str) << std::endl;
    return 0;
}

程序运行正常,输出符合预期

./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....
./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....

为什么它会在第一个场景中崩溃?

2 个答案:

答案 0 :(得分:3)

您的输入字符串为120字节宽。您的C字符串缓冲区宽80字节。 HRMM。

使用查找函数代替这个容易出错的C废话!!

自上次|以来获取所有内容:

#include <iostream>
#include <string>
#include <stdexcept>

std::string getString(const std::string& fullString)
{
    size_t pos = fullString.rfind('|');
    if (pos == std::string::npos)
       throw std::runtime_error("Could not find a '|'!");

    return fullString.substr(pos+1);
}

int main()
{
    std::string str("{[(2015/11/30|01:07:53.357|-1227639088|DefaultThread|./src/Myprogram.cpp:564|int main(int, argv**))]} Server Starting....");
    std::cout << getString(str) << std::endl;
}

live demo

根据需要进行调整,以扫描第2,第3,第4 |

答案 1 :(得分:2)

您的程序具有未定义的行为,因为str中存储的字符串长度大于80个字符。因此在本声明中

strcpy(string, fullString.c_str());

你将内存覆盖在数组字符串之外。

Moverover使用C函数strtok而不是类find的成员函数rfind(或std::string)是一种不好的方法。

还不清楚为什么在循环中使用了精确的数字4

for(int i = 0; i < 4; i++){
    endString = strtok(NULL, "|");
}