c++exceptiontry-catchifstreamofstream

Why the following code works, but if I add "fin.exceptions(ifstream::badbit | ifstream::failbit);" to make the second try/catch work, I get an error?


My code:

int main() {
    string path = "D:\\myFile.txt";
    Point pointOfIllusion(1, 2, 3);
    Point pointOfDesilusion(3, 2, 1);
    ofstream fout;
    
    fout.exceptions(ofstream::badbit | ofstream::failbit); **// everything is ok with this string**
    try {
        cout << "Trying to read the file\n";
        fout.open(path, ofstream::app); 
        cout << "The file has been successfully created and opened\n";
    }
    catch(const ofstream::failure& ex){
        cout << ex.what() << endl;
        cout << ex.code() << endl;
        perror ("Could not open the file");
        abort();
    }
    fout.write((char*)&pointOfIllusion, sizeof(Point));
    fout.write((char*)&pointOfDesilusion, sizeof(Point));

    fout.close();
    
    ifstream fin;
    fin.exceptions(ifstream::badbit | ifstream::failbit); **// If I put this, it causes an error, described below, but without this string the following try/catch doesn't work**
    try {
        cout << "Trying to read the file\n";
        fin.open(path);
        cout << "The file has been successfully opened\n";
    }
    catch (const ifstream::failure& ex) {
        cout << ex.what() << endl;
        cout << ex.code() << endl;
        perror ("Could not open the file");
        abort();
    }
    
    Point tempPoint;
    size_t length = 0;
    while (fin.read((char*)&tempPoint, sizeof(Point))) { **// The debugger throws the exception when I add the string above in this place, however I do not modify it at all**
        length++;
    }

    fin.clear();
    fin.seekg(0, ios::beg);
    
    Point* Points = new Point[length];
    for (size_t i = 0; i < length; i++)
        {
            fin.read((char*)&Points[i], sizeof(Point));
            Points[i].Print();
        }
        delete[] Points;
        
    fin.close();
    getchar();
    return 0;
}

I get an error in the loop:

while (fin.read((char*)&tempPoint, sizeof(Point))) {
    length++;
}

The error is the following:

An exception was raised at address 0x0000007FFECCC3CF19 in WorkWithFiles.exe: Microsoft C++: std::ios_base::failure exception at memory address 0x0000000059CBAFEF80.
An unhandled exception occurred at address 0x0000007FFECCCCC3CF19 in WorkWithFiles.exe: Microsoft C++ exception: std::ios_base::failure at memory address 0x00000059CBAFEF80.

Without this code:

fin.exceptions(ifstream::badbit | ifstream::failbit);

there is no such errors and the program works, however it doesn't catch exceptions when using second try/catch block (with fin object). Only that of fout works.

Could you tell me, please, what I'm doing wrong?

I tried to practice try/catch with ifstream/ofstream objects, while opening the file with correct and wrong addresses.


Solution

  • Without

    fin.exceptions(ifstream::badbit | ifstream::failbit);

    So, this happens when this line is left in place. This line tells your computer to throw an exception if any operation on fin fails (the differences between the two states are immaterial here).

    while (fin.read((char*)&tempPoint, sizeof(Point))) {
    

    This line tells your computer to keep calling read() until fin is no longer in a good state. However, according to The Golden Rule Of Computer Programming, which says "your computer always does exactly what you tell it to do instead of what you want it to do", a failed read() will end up throwing an exception. So that's why this line ends up throwing an exception: because that's what you told your computer to do, when fin's status changes to a failed state. The fact that there's a loop that calls read(), until that happens, doesn't change that. The exception gets thrown by fin itself, as part of read(), it never returns and the exception gets thrown, so the while loop never has a change to check fin's state.