简体   繁体   中英

Segmentation fault when reading text file

I am trying to run a code sorting the ages of Titanic survivors from a text file. It compiles fine, but the program terminates simply saying "segmentation fault" when I choose option B (option A is not written yet.) Here is a small sample of the text file for reference.

29 1stClass TRUE

0.9 1stClass TRUE

2 1stClass FALSE

30 1stClass FALSE

I've isolated the error to the chunk where the file is processed (//actual processing), but I'm not sure what exactly is wrong.

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <fstream>
#include <ctype.h>

void sortSurvivors();
void sortAgesLiving();

int main()
{
    char options;
    std::cout << "Titanic Data \nOptions \nA) Display count of people who lived and died... \nB) Display count of people who lived by age... \nPlease select option (A-B)...";
    std::cin >> options;
    switch (options)
    {
        case 'A':
            sortSurvivors();
            break;
        case 'B':
            sortAgesLiving();
            break;
    }
}

void sortSurvivors()
{

}

void sortAgesLiving()
{
    std::ifstream inputFile;
    std::string filename = "TitanicData.txt";
    std::string age;
    std::string classBoat;
    std::string survival;
    bool survived;
    int eldest = 0;

    //pre-sort processing
    while (inputFile >> age >> classBoat >> survival)
    {
        int ageConv = stoi(age);
        //G is for the ghetto fix I am pulling here, because I recieve an error when using "TRUE" as a string
        char gchar = 'G';
        survival += gchar;
        if (survival == "TRUEG")
        {
            survived = true;
        }
        else
        {
            survived = false;
        }
        if (eldest < ageConv) 
        {
            eldest = ageConv;
        }
    }

    //initialize vector
    std::vector<int> survivorVector;
    for (int i = 0; i < eldest; i++)
    {
        survivorVector.push_back(0);
    }

    inputFile.open(filename);
    //actual processing (ERROR HERE)
    if (inputFile)
    {
        while (inputFile >> age >> classBoat >> survival)
        {
            int ageConv = stoi(age);

            if (survived = true)
            {
                survivorVector[ageConv] = survivorVector[ageConv] + 1;
            }
            for (int j = 0; j <= eldest; j++)
            {
                std::cout << j << "\t" << survivorVector[j] << "\n";
            }
        }

        // Close the file.
        inputFile.close();
    }
    else
    {
        std::cout << "I don't know what broke, but uhhhhhhhhhh oops.";
    }
}

As per usual I'm sure it's something dumb I overlooked.

In sortAgesLiving() , you have forgotten to open the file before starting your pre-sort processing. As a consequence, your first reading loop will fail to read anything at all. Therefore eldest will stay 0.

You then construct a vector and populate it. But since the loop is based on eldest , the vector survivorVector will stay empty.

When you finally open the file and read it, the first line will be considered as a survivor since you accidentally overwrite the boolean with true (ie if (survived = true) instead of if (survived == true) or simply if (survived) . You'll then try to access the vector out of bounds.

Even if you correct this error, at the first survivor you'll get again out of bounds. Accessing a vector out of bounds is UB and one of the many possible symptoms can be segmentation fault.

Miscellaneous advices (not related to your issues) :

  • You have an ambiguous age of 0.9 . Converting it to an int will cause it to be 0. Is this ok, or do you need to round this up?
  • If it's rounding up, you could make the age variable a double and read it directly without conversion. You could then convert it mathematically to an integer age rounding it up or truncating it, as needed. If you're sure to have only integers, you could make the variable an int and not worry at all.
  • It is unsafe to trust a value in a file to directly index a vector. What if between the two reading phases, an additional line would have been added by someone else to the file with a value higher than eldest ? What if the value read would be negative? Better always check that it's in an acceptable range before using a value as an index. It can save you hours of debugging and your customers some nightmares.
  • Finally, the two-phase read is not necessary: you could just read the age, and after having checked that it's positive and smaller than 150 years (quite optimistic), you could, if needed, resize your vector if the age is equal or larger than the current vector size. Why? Imagine you work one day for US census with files having millions of lines: the fewer passes over the file, the better;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM