2012-03-01 101 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

相關問題