Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Unhandled exception when reading file

Trying to write .ply parser to use .ply models in OpenGL.

Trying to begin to read the .ply file and write all the lines of it out. My program does this but when it print out the last line i get Unhandled exception:

Unhandled exception at 0x62aad540 (msvcr100d.dll) in PLY parser.exe: 0xC0000005: Access violation reading location 0x00000000.

This is my code:

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

This may be foolish error in my code, but it would be great if someone can spot the error causing this.


2 Answers

Before we get into what the bug is, you should know that the "Unhandled exception ... Access violation reading location 0x00000000" message you get is not caused by a C++ exception; it's the Windows equivalent of "Segmentation fault". Your code tried to dereference the NULL pointer.

Now, you have made one of the classic mistakes in working with FILE objects. feof(fp) does not become true when you reach the end of the file. It only becomes true after you have attempted to read past the end of the file at least once. Thus, your read loop will iterate until after fgets attempts to read past the end of the file. And when fgets attempts to read past the end of the file, it fails, and returns a NULL pointer, which you blindly passed to cout. Kaboom.

(By the way, this is also how istream::eof() works.)

The correct way to write this loop is

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

(Or, even better, one of these:

while (fgets(buffer, 10000, myFile))
    fputs(buffer, stdout));

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

it being a little weird to mix stdio.h FILEs and iostreams as you are doing.)

like image 198
zwol Avatar answered May 30 '26 10:05

zwol


feof() tells you that you've tried to read past the end of file, not that you've reached the end of file. fgets() returns NULL when you're at the end of file and there's no more data to read. That's where the exception is coming from. At the end of file, feof() will return false and fgets() will return NULL, which will cause the exception when your program tries to execute cout << NULL;.

This is the idiomatic way to write it in C style:

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

or in C++ style:

std::string buffer;
std::ifstream myFile("walkman.ply");
if (myFile.is_open()) {
    while (std::getline(myFile, buffer)) {
        std::cout << buffer << '\n';
    }
}
like image 26
Ferruccio Avatar answered May 30 '26 11:05

Ferruccio