首页 文章

C读取文件时出现未处理的异常

提问于
浏览
2

尝试编写.ply解析器以在OpenGL中使用.ply模型 .

试图开始读取.ply文件并写出它的所有行 . 我的程序执行此操作但是当它打印出最后一行时,我得到Unhandled exception:

PLY parser.exe中0x62aad540(msvcr100d.dll)的未处理异常:0xC0000005:访问冲突读取位置0x00000000 .

这是我的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>


using namespace std;


int main ()
{
    char buffer[10000];
    FILE * myFile;
    myFile = fopen("walkman.ply", "r");
    if(myFile != NULL)
    {
        while (!feof(myFile))
        {

               cout<<fgets(buffer, 10000, myFile);

        }
        fclose(myFile);
    }
    else
    {
        cout<<"file not found"<<endl;
    }

    system("pause");
    return 0;
}

这可能是我的代码中的愚蠢错误,但如果有人能够发现导致此错误的错误,那将会很棒 .

3 回答

  • 6

    feof() 告诉你've tried to read past the end of file, not that you'已到达文件末尾 . 当're at the end of file and there'没有更多数据要读取时 fgets() 返回NULL . 这就是异常的来源 . 在文件末尾, feof() 将返回false, fgets() 将返回 NULL ,这将在程序尝试执行 cout << NULL; 时导致异常 .

    这是用C风格编写它的惯用方法:

    char buffer[10000];
    FILE* myFile = fopen("walkman.ply", "r");
    if (myFile != NULL) {
        while (fgets(buffer, sizeof(buffer), myFiles) {
            fputs(buffer, stdout);
        }
        fclose(myFile);
    }
    

    或C风格:

    std::string buffer;
    std::ifstream myFile("walkman.ply");
    if (myFile.is_open()) {
        while (std::getline(myFile, buffer)) {
            std::cout << buffer << '\n';
        }
    }
    
  • 0

    在我们了解bug之前,您应该知道您获得的"Unhandled exception ... Access violation reading location 0x00000000"消息不是由C异常引起的;这是Windows等效的"Segmentation fault" . 您的代码尝试取消引用NULL指针 .

    现在,您在处理 FILE 对象时犯了一个经典错误 . 到达文件末尾时 feof(fp) 不会成立 . 只有在尝试至少读取一次文件末尾 past 之后,它才会成立 . 因此,您的读取循环将迭代,直到 fgets 尝试读取超过文件末尾 . 当 fgets 尝试读取超过文件末尾时,它会失败,并返回一个NULL指针,您将盲目地传递给 cout . KABOOM .

    (顺便说一句,这也是 istream::eof() 的工作原理 . )

    编写此循环的正确方法是

    while (fgets(buffer, 10000, myFile))
        cout << buffer;
    

    (或者,甚至更好,其中一个:

    while (fgets(buffer, 10000, myFile))
        fputs(buffer, stdout));
    
    while(myFile.get(buffer, 10000))
        cout << buffer;
    

    正如你所做的那样,将 stdio.h FILE和 iostream 混合起来有点奇怪 . )

  • 4

    编辑:我的预后错误,但如果您打算使用流,仍然会阅读以下内容 .

    另外请考虑使用流(in)和向量,这些方法不易出错,并且符合C风格和精神 .

    std::ifstream in("walkman.ply", std::ios::binary);
    std::vector<char> v(istream_iterator<char>(in),
                        istream_iterator<char>( ));
    

    或者如果那是一个字符串值 .

    std::ifstream in("walkman.ply");
    std::string str(istream_iterator<char>(in),
                    istream_iterator<char>( ));
    std::cout << str << std::endl;
    

相关问题