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

时间:2012-03-01 20:29:15

标签: c++ unhandled-exception

尝试编写.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 个答案:

答案 0 :(得分:6)

在我们了解bug之前,你应该知道你得到的“未处理的异常...访问冲突读取位置0x00000000”消息是由C ++异常引起的 not ;它是Windows的“Segmentation fault”等价物。您的代码尝试取消引用NULL指针。

现在,您在处理FILE个对象时犯了一个经典错误。当您到达文件末尾时,feof(fp)不会成立。只有在尝试读取过去文件末尾至少一次后,才会成为现实。因此,您的读取循环将迭代,直到 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混合在一起有点奇怪。)

答案 1 :(得分:4)

feof()告诉您,您已尝试读取文件末尾,而不是已到达文件末尾。当您在文件末尾时,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';
    }
}

答案 2 :(得分:0)

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

另外请考虑使用stream(in)和vector,这些方法不易出错,并且符合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;