Linux |C++中的分段错误 - 由于函数 ifstream

Linux | Segmentation Fault in C++ - Due to the function ifstream

本文关键字:于函数 函数 ifstream C++ 错误 分段 Linux      更新时间:2023-10-16

我想我应该首先说我刚刚在我的电脑上安装了linux(debian(,并且对在Linux中做事没有任何预知。这个问题可能是由于一些非常简单的事情。

代码的相关部分类似于以下内容:

ifstream stockNames("names.txt");
    while (!stockNames.eof())
    {
        string snline;
        getline(stockNames,snline);
        cout << snline << endl;
        .
        .
        .
    }

这应该打印文件"名称.txt"的第一行。相反,它会打印一个空行。当我尝试在另一个函数中使用snline作为输入时,我收到错误"分段错误"。我应该如何修改我的代码来执行此操作?ifstream在linux中的使用有什么区别吗?因为在窗口中代码工作正常


我在下面编写了简单的代码

#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
    string dos = "names.txt";
    ifstream stockNames(dos.c_str() );
    string snline;
    while (getline(stockNames,snline))
    {
       cout << snline << " ";
    }
    return 0;
}

名称的内容.txt是

美国广播公司

德夫格

高压氧

Cout <<SNLINE 不会显示这些行,而是不产生任何结果


再更新一次:我又写了两个代码。

(1(

#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
    cout << "program has initiated" << endl;
    ifstream stockNames("names.txt");
    if( !stockNames )
        cout << "unable to open" << endl;
    string snline;
    while (getline(stockNames,snline))
    {
        cout << snline << endl;
    }
    return 0;
}

结果如我所愿。首先是"节目已经启动",然后是ABC,DEFG,HBO在不同的行中。但是当我改变这部分时

        cout << snline << endl;

        cout << snline << " hey" << endl;

然后ABC DEFG HBO不会出现,唯一的输出是"嘿"。

这太疯狂了,这怎么可能??

顺便说一句,我尝试使用 ddd 进行调试,当我检查变量 snline 时,ddd 打印以下行(gdb( 打印 SNLINE$2 = {静态 npos = 4294967295, _M_dataplus = {> = {<__gnu_cxx::new_allocator> = {}, }, _M_p = 0x804c1a4 "ABC\r"}}

新的迷你更新:当我将相关行更改为"cout <<snline <<""<<endl;"时,打印出来的是"BC"FGH"BO"在单独的行中。为什么<<运算符会覆盖 snline?

首先,你的while循环是错误的,因为eof标志(或任何其他失败标志(是在尝试从流中读取失败设置的;这意味着,如果使用getline()尝试读取失败,循环不会立即退出,而是循环继续,这是代码的一个严重错误。

所以把你的循环写成(一种惯用的方式(:

string snline;
while (getline(stockNames,snline))
{
    cout << snline;
    //..
}

std::getline返回 istream& ,可以隐式转换为布尔类型。因此,如果getline成功读取,则返回的值将转换为 true 并且循环将继续,否则它将转换为 false 并且循环将退出。


在您的问题中进行编辑之后,我只能说您需要在使用它从文件中读取内容之前检查流对象。更具体地说,您需要检查流是否已正确初始化,并且确实打开了输入文件(即names.txt(,并准备好从中读取数据。

因此,请尝试这样做:

//...
ifstream stockNames(dos.c_str() );
if (!stockNames) 
{
     cout << "file couldn't open properly" << endl;
     return 0;
}
string snline;
while (getline(stockNames,snline))
{
   cout << snline << " ";
}

现在运行它,看看它打印了什么。

您有一个在每行末尾使用 \r 的 dos 文件。Linux 不识别 \r 作为行尾的一部分,因此它包含在 snline 字符串中。\r 使打印的下一项出现在行首,因此"hey"会覆盖您期望看到的股票名称。

尝试

cout << snline << " " << endl;

你会明白我的意思

stockNames 实际上不会到达"文件末尾",直到它尝试输入某些内容并收到 EOF 字符。因此,您需要重写循环,如下所示:

ifstream stockNames("names.txt");
string snline;
getline(stockNames,snline);
while (!stockNames.eof())
{
    cout << snline << endl;
    .
    .
    .
    getline(stockNames,snline);
}

或者很简单

ifstream stockNames("names.txt");
string snline;
while (getline(stockNames, snline))
{
    cout << snline << endl;
    .
    .
    .
}

回答你的问题;不,ifstream在Linux和Windows上的运行方式没有显着差异。当然,如果你写了错误的代码(正如其他两个答案所指出的那样(,那么你可能会遇到问题,但我看不出 eof bug 会导致你所描述的问题。

我会专注于您说使用 snline 会导致分段错误的部分,这表明这是一个更严重的问题。你能发布说明这一点的代码吗?

您没有检查流是否正确打开。

std::ifstream stockNames("names.txt");
if (! stockNames) {
    std::cerr << "Unable to open file 'names.tex'n";
}
else {
   // Do the rest of your stuff here.
}

始终检查状态。不要只是向前耕耘,假设一切都很好。

顺便说一句,using namespace std;是你在很多试图节省少量墨水的坏书中看到的东西。试着摆脱这个坏习惯。