0

I have written some code in c++. It reads in data from a CSV file and then simply prints the second line to the screen:

vector<string> readCsvFileContent()
{
    vector<string> buffer;

    try {
        ifstream inputFile;
        string line;

        inputFile.open("Input.csv", static_cast<std::ios::openmode>(std::ios::in) );

        while (getline(inputFile,line)) {
            buffer.push_back(line);
        }

       inputFile.close();
    }
    catch (ifstream::failure e) { 
        cout<<"No file read"<<endl;            
        throw e;
    }

    return buffer;
}

This function is called as follows :

cout << "reading from file" << endl;
vector<string> inputData = readCsvFileContent();
cout << inputData.size() << endl;
cout << inputData[1] << endl;

When it runs in debug it displays what it should:

[ 50%] Building CXX object src/CMakeFiles/version1.dir/version1.cc.o
Linking CXX executable version1
[ 50%] Built target version1
[100%] Generating House1.csv
reading from file
322274
"2014-07-01 00:00:06",155,0,0,0,NULL,0,0,0,0,NULL
[100%] Built target process_csv

But when I run my code I get:

reading from file
0
Segmentation fault (core dumped)
Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40
Valkyrie
  • 108
  • 13
  • this usually means the file is not open correctly; please mind that you don't test for this in your code. – Pandrei Feb 02 '15 at 12:28
  • `static_cast` and `inputFile.close();` are unnecessary. I've never used stream exceptions so can't comment on that.. – Neil Kirk Feb 02 '15 at 12:31
  • 1
    @lurker No it's returned from the function by value. That's fine. – Neil Kirk Feb 02 '15 at 12:31
  • 2
    Do not cast the opening method. What for are you doing it? Just `open(file,mode)` – ForceBru Feb 02 '15 at 12:32
  • 1
    Your problem lies outside of the function you posted. – molbdnilo Feb 02 '15 at 12:38
  • lurker seemed to have deleted the piece of code that I have the problem with. – Valkyrie Feb 02 '15 at 12:41
  • The error probably occurs when you read the vector, not write to it. – Neil Kirk Feb 02 '15 at 12:44
  • @Lands lurkers version seems identical to the one you posted except for whitespace. I can't reproduce the problem with your code either unfortunately [coliru](http://coliru.stacked-crooked.com/a/74e5b5d90e94207d) (this has your version of the function). – eerorika Feb 02 '15 at 12:48
  • When my int main looks like this I get the mistake: 'cout<<"reading from file"< inputData = readCsvFileContent(); cout< – Valkyrie Feb 02 '15 at 12:51
  • @Lands put the relevant code in your question. – eerorika Feb 02 '15 at 12:53
  • 2
    @Lands the main function, combined with the output, reveals why the segfault happens. Your main prints the size of the vector which is **0** in the output. Therefore `inputData[1]` has undefined behaviour. So, the problem is that either the file is empty, doesn't exist or isn't readable. Perhaps you're running your debug and release builds differently? Maybe they have different working directories and only debug actually has the file? Perhaps the file exists in the release directory with wrong permissions. Your code really should check that it has actually opened a (non-empty) file. – eerorika Feb 02 '15 at 13:00
  • If you want an exception on failure, you need to ask the stream for it first: `inputFile.exceptions(std::ifstream::failbit);`. – molbdnilo Feb 02 '15 at 13:16
  • 1
    You don't know how many lines are in a file. Therefore don't hardcode a line access without checking the size first. – Neil Kirk Feb 02 '15 at 13:31
  • when I output the string line as I read it in, it prints out the correct value of the file. It just refuses to add it to the vector – Valkyrie Feb 02 '15 at 14:52
  • There is no such thing as "refuses". If you have code, which works as you expected (printing the line read), then show us the whole example. Moreover, as no one is able to reproduce it, either you are not showing the code you have a problem with or problem lays in the way you build. – zoska Feb 03 '15 at 13:37

1 Answers1

4

You get a segfault because you read beyond the vectors borders

inputData.size() // 0 i.e. empty
inputData[1] // undefined behaviour

Your code should check whether a file was opened succesfully. You can do this:

if (!inputFile.is_open())
    // throw or whatever

Or, since you seem to already be prepared for it with a try-catch, as molbdnilo points out, you can ask the stream to throw on failure:

inputFile.exceptions(std::ifstream::failbit);

To test if the file was empty, just check inputData.size() which you already print, but ignore.

Now, the remaining question is, why does it work in debug but not in release? Well, my crystal ball is out of battery but I can speculate that your builds have different working directories and the file is missing or not readable in the other one. You haven't told about what your build does but this might be relevant:

[100%] Generating House1.csv

inputFile.open("Input.csv", static_cast(std::ios::in) );

eerorika
  • 232,697
  • 12
  • 197
  • 326