为什么以下代码有效,但是如果我添加“fin.exceptions(ifstream::badbit |ifstream::failbit);“ 要使第二次 try/catch 正常工作,我收到错误?

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?

提问人:Alma Latina 提问时间:10/26/2023 最后编辑:Remy LebeauAlma Latina 更新时间:10/27/2023 访问量:79

问:

我的代码:

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

我在循环中收到一个错误:

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

错误如下:

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.

如果没有此代码:

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

没有这样的错误,程序可以工作,但是在使用第二个/块(带对象)时它不会捕获异常。只有作品。trycatchfinfout

你能告诉我,我做错了什么吗?

我尝试练习 / with / 对象,同时打开具有正确和错误地址的文件。trycatchifstreamofstream

C++ 异常 try-catch ifstream ofstream

评论

0赞 463035818_is_not_an_ai 10/26/2023
请显示重现错误的代码,而不是需要修改才能重现错误的代码。此外,请尝试删除重现错误不需要的代码。阅读有关最小可重复示例的信息。
0赞 463035818_is_not_an_ai 10/26/2023
在你的代码中有。这是你在标题中提到的那一行吗?fout.exceptions(ofstream::badbit | ofstream::failbit);
0赞 Alma Latina 10/26/2023
@463035818_is_not_an_ai,谢谢你的回答。我的代码中有 2 个类似的块。你说的指的是“fout”对象。我使用“fout”对象创建一个文件(“D:\\myFile.txt”)并将我的数据写入其中。但我还有第二个“fin”对象,我用它来读取文件中的数据。fout.exceptions没有问题...字符串,但是如果我为“fin”对象添加一个类似的字符串,即“fin.exceptions(ifstream::badbit|ifstream::failbit);”我开始收到上面描述的错误。正如我在调试器中看到的那样,错误发生在下面的 while 循环中,我没有更改。
0赞 463035818_is_not_an_ai 10/26/2023
下面的答案解释了这个问题。我没有发现这个 while 循环在您的 try catch 之外(如果您显示导致错误的代码而不是解释必须如何修改它,这将非常简单)。如果抛出异常并且未捕获到异常,则程序将终止。你添加的那一行告诉抛出异常。fin
0赞 463035818_is_not_an_ai 10/26/2023
我也不明白为什么你写到的两行和另一行不在 try catch 内。此外,你告诉流抛出异常,但同时你没有正确处理可能的异常。foutfout.write((char*)&pointOfIllusion, sizeof(Point));

答:

1赞 Sam Varshavchik 10/26/2023 #1

没有

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

因此,当这条线留在原位时,就会发生这种情况。此行告诉您的计算机在执行任何操作失败时引发异常(两种状态之间的差异在这里无关紧要)。fin

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

此行告诉您的计算机继续调用,直到不再处于良好状态。然而,根据《计算机编程的黄金法则》,即“你的计算机总是完全按照你的指示去做,而不是你想让它去做”,失败最终会引发异常。所以这就是为什么这一行最终会抛出一个异常:因为这是你告诉计算机要做的,当 的状态变为失败状态时。事实上,有一个循环调用,直到这种情况发生,并不能改变这一点。异常会自行抛出,作为 的一部分,它永远不会返回,并且异常会被抛出,因此循环永远不会更改以检查 的状态。read()finread()finread()finread()whilefin

评论

2赞 James Kanze 10/26/2023
作为一般规则,至少在输入文件上抛出异常不是一个好主意,正是因为这是输入已完成的标准通知。(on 的异常很好,on 输出可能也很好。failbitbadbitfailbit
0赞 Alma Latina 10/26/2023
@JamesKanze,谢谢!我已经删除了输入文件中的“failbit”,它没有它也能正常工作。