【问题标题】:Linux | Segmentation Fault in C++ - Due to the function ifstreamLinux | C++ 中的分段错误 - 由于函数 ifstream
【发布时间】:2011-08-03 18:41:50
【问题描述】:

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

相关部分代码类似这样:

ifstream stockNames("names.txt");

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

这应该打印文件“names.txt”的第一行。相反,它打印一个空行。当我尝试在另一个函数中使用 snline 作为输入时,我收到错误“分段错误”。我应该如何修改我的代码来做到这一点? linux中ifstream的用法有什么不同吗?因为在 Windows 中代码工作得很好


我已经写了下面的简单代码

#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;
}

names.txt 的内容是

ABC

DEFG

HBO

cout


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

(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 = {> = {<:new_allocator> = {}, }, _M_p = 0x804c1a4 "ABC\r"}}

新的迷你更新:当我将相关行更改为 "cout

【问题讨论】:

  • 你确定names.txt在正确的目录吗?
  • "ABC\r":您的文件中有 windows 行终止符。用 dos2unix 打它。

标签: c++ linux


【解决方案1】:

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

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

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

std::getline 返回istream&amp;,可以隐式转换为布尔类型。所以如果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 << " ";
}

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

【讨论】:

  • 我已经进行了修改,但问题仍然存在。 snline 打印为空。
  • @aristos:抱歉,如果没有看到更多代码和names.txt 的内容,我无法提供进一步帮助。
  • 我已经把新代码放上来了,如果可以的话,你可以看看吗
【解决方案2】:

你有一个在每行末尾使用 \r\n 的 dos 文件。 Linux 不将 \r 识别为行尾的一部分,因此它被包含在 snline 字符串中。 \r 使下一个打印的内容出现在行首,因此“嘿”会覆盖您希望看到的股票名称。

试试

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

你会明白我的意思

【讨论】:

  • 就是这样!我应该怎么做才能保持股票名称不变?
  • 要么将文件转换为 Linux/Unix 行结尾,要么手动删除 snline 末尾的 \r。如果你给我的答案打勾也很好:)
  • 世界上所有的蜱虫约翰。非常感谢=)
【解决方案3】:

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;
    .
    .
    .
}

【讨论】:

  • 我已经进行了修改,但问题仍然存在。 snline 打印为空。
  • 您能否确认您确实在拾取您认为的文件?你确定它正在获取 names.txt 吗?
  • 是的,如果您可以检查我在线程中所做的新更新,我已经添加了一行来检查文件是否已成功打开。正如您在我提到的更新中看到的那样,有一些非常奇怪的东西
【解决方案4】:

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

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

【讨论】:

  • 我认为seg错误是由于空输入snline。我编写了一个简单的代码来显示文件名.txt 中的内容,但它不起作用
  • 嗯,我确信这是由您的代码中的错误引起的,您在 Windows 上逃脱了,但在 Linux 上却没有。如果您发布一个完整的程序,我相信它很快就会得到修复。在那之前,这将是一个谜。
  • @aristos 使用完整代码编辑您的问题,请不要将我们链接到其他网站。
【解决方案5】:

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

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; 是您在许多试图节省少量墨水的糟糕书籍中看到的东西。试着改掉这个坏习惯。

【讨论】:

  • 谢谢,我刚刚添加了。请您检查原始帖子中的最新更新。我认为
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
相关资源
最近更新 更多