为什么在正常情况下使用std::ifstream会导致分段错误

Why does using std::ifstream under normal circumstances give me a segmentation fault?

本文关键字:分段 错误 ifstream std 为什么 在正常情况下      更新时间:2023-10-16

很抱歉,如果我问的任何问题是显而易见的或愚蠢的,我已经学习C++大约两周了。

EDIT:我发现了问题,在文件的输出中,所有空格都被更改为不同的字符。有人能结束这个问题吗?

我一直在尝试编写一个程序来收集假设员工的数据。最近,我尝试让它从文件中读取——然而,每次运行下面的代码(运行fix();)时,我都会遇到分段错误。使用断点,我将其缩小到std::ifstream file(filename)。我对它进行了测试,发现filename变量不是问题所在——即使我使用字符串文字,它仍然会抛出错误。我发现的其他东西:

-分离std::ifstream file(filename)并将其放入另一个文件中,在该文件中它不能引用该文件的任何变量,这样做效果很好。

-当我输入一个不存在的文件的名称时,分段错误确实发生了,相反,它会到达断点0(像它应该的那样),打印Error in opening file.(像它应当的那样)并返回false(像它理应的那样)。

有人知道为什么会发生这种情况以及如何解决吗?这件事已经困扰我好几天了。

(此外,我使用的是带有G++4.8的Ubuntu 14.04-启动标志-std=c++1y)

编辑好的,这变得非常奇怪。我做的第一件事是每隔一行使用std::cout调试我的程序。这就把问题指向了std::ifstream。然而,在@M.M和@hyde的建议下,我通过Code::Blocks调试器运行了我的程序。它告诉我分割错误发生在emp->firstName = lineList[2]。所以我把那行注释掉了——但调试器仍然说那行是问题所在!据说问题是一条评论线!我比以往任何时候都更困惑。

#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include "baselibrary.h"
struct Employee
{
    int16_t id; // Employee ID
    std::string lastName; // Employee's last name
    std::string firstName; // Employee's first name
    char middleInitial; // Employee's middle initial
    int16_t age;
    bool gender; // false is male, true is female
    float salary;
    int16_t experience; // # of years working at company
    int16_t department; // Department from Departments::
};
std::vector<Employee> employeeArrayN;
int empNumN{1};
//... tons of snipped out code ...//
bool loadFromDatabaseFileN(){
    std::string filename;
    std::cout << "Please enter filename to load (with extension): ";
    std::getline(std::cin, filename);
    std::ifstream file(filename);
    std::cout << "Breakpoint 0!";
    if (!file){
        std::cout << "Error in opening file. ";
        return false;
    }
    std::cout << "Breakpoint 1!";
    while (file) // ifstream returns 0 when reaching EOF - 0 is boolean false
    {
        // it's probably OK to ignore the code under here, but you never know...
        std::string lineInput;
        std::cout << "Breakpoint 2!";
        Employee *emp = new Employee;
        std::cout << "Breakpoint 3!";
        ++empNumN;
        std::cout << "Breakpoint 4!";
        std::getline(file, lineInput);
        std::vector<std::string> lineList = splitString(lineInput, ' ');
        int16_t tempId;
        std::cout << "Breakpoint 5!";
        std::stringstream(lineList[0]) >> tempId;
        emp->id = tempId;
        emp->lastName = lineList[1];
        emp->firstName = lineList[2];
        char tempMInit;
        std::stringstream(lineList[3]) >> tempMInit;
        emp->middleInitial = tempMInit;
        int16_t tempAge;
        std::stringstream(lineList[4]) >> tempAge;
        emp->age = tempAge;
        bool tempGend;
        std::stringstream(lineList[5]) >> tempGend;
        emp->gender =  tempGend;
        float tempSalary;
        std::stringstream(lineList[6]) >> tempSalary;
        emp->salary = tempSalary;
        int16_t tempExperience;
        std::stringstream(lineList[7]) >> tempExperience;
        emp->experience = tempExperience;
        int16_t tempDepartment;
        std::stringstream(lineList[8]) >> tempDepartment;
        emp->department = tempDepartment;
        employeeArrayN.resize(empNumN);
        employeeArrayN[empNumN - 1] = *emp;
        std::cout << "Added new employe: [ID " << emp->id << "] " << emp->lastName << ", " << emp->firstName << " " << emp->middleInitial << ". n";
    }
    file.close();
    return true;
}
//...snip...//
//fix is a function I added just for this question, I wouldn't want to bother you with my monolithic actual function//
void fix()
{
    bool notGonnaUse = loadFromDatabaseFileN();
}

这可能无法解决您的问题,但。。。

使用

while ( file )
{
   ...
   std::getline(file, lineInput);
   ...
}

是个问题。请参阅为什么循环条件中的iostream::eof被认为是错误的?。

使用

while ( file ) { }

遇到与使用相同的问题:

while ( !file.eof() ) { }

更改代码以使用:

// Move the declaration of lineInput out of the loop.
std::string lineInput;
while ( std::getline(file, lineInput) )
{
   ...
}