2012-03-01 103 views
2

试图编写.ply解析器以在OpenGL中使用.ply模型。C++读取文件时出现未处理的异常

尝试开始读取.ply文件并将其写出所有行。 我的程序做到这一点,但是当它打印出的最后一行我得到未处理的异常:在PLY parser.exe在0x62aad540(msvcr100d.dll)

未处理的异常:0000005:访问冲突读取位置00000000。

这是我的代码:

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

这可能是我的代码中愚蠢的错误,但是这将是巨大的,如果有人能找到这个错误导致此。

+1

但是你根本没有使用''。 – Seagull 2012-03-01 20:33:34

回答

6

在我们进入的错误是什么,你应该知道“未处理的异常...访问冲突读取位置0x00000000“您收到的消息是而不是由C++异常引起;这是Windows的“分段故障”等效物。你的代码试图解引用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文件和iostream S作为你在做什么。)

0

编辑:我的预测错了,但仍然阅读以下,如果你打算使用流。

另外请考虑使用流(中)和向量,这些方法是很少容易出错,适合与C++风格和ethos。

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; 
+0

这可能会发生,但它会为访问冲突提供不同的地址。现在它引用0x0000000,这意味着某个地方程序正在解引用NULL指针。 – 2012-03-01 20:39:12

+0

@MatteoItalia要钝我认为这是一个C问题,而不是C++,如果错误仍然存​​在于上面给出的流实现中,请让我知道。 – 111111 2012-03-01 20:40:49

+0

我并不是说你的解决方案是错误的,但你的诊断是不正确的。 – 2012-03-01 20:42:25

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'; 
    } 
} 
+0

'fgets'不会修剪终止换行符,所以你必须将它与'fputs',而不是'puts'配对。 – zwol 2012-03-01 20:49:11

+0

@Zack:谢谢。自从我编写了生产C代码以来,这已经过去了很久。 – Ferruccio 2012-03-01 20:53:01

相关问题