C ++读取文件时未处理的异常
Posted
技术标签:
【中文标题】C ++读取文件时未处理的异常【英文标题】:C++ Unhandled exception when reading file 【发布时间】:2012-03-01 20:29:15 【问题描述】:尝试编写 .ply 解析器以在 OpenGL 中使用 .ply 模型。
尝试开始读取 .ply 文件并写出它的所有行。 我的程序会这样做,但是当它打印出最后一行时,我得到未处理的异常:
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;
这可能是我的代码中的愚蠢错误,但如果有人能发现导致此错误的错误,那就太好了。
【问题讨论】:
但是你根本没有使用<fstream>
。
【参考方案1】:
在我们深入了解错误是什么之前,您应该知道您收到的“未处理的异常...访问冲突读取位置0x00000000”消息不是由C++异常引起的;它相当于 Windows 的“分段错误”。您的代码试图取消引用 NULL 指针。
现在,您在使用FILE
对象时犯了一个经典错误。当您到达文件末尾时,feof(fp)
不会变为真。只有在您尝试读取过去文件末尾至少一次后,它才会变为真。因此,您的读取循环将迭代直到 after fgets
尝试读取文件末尾。当fgets
尝试读取文件末尾之后,它失败,并返回一个空指针,你盲目地将它传递给cout
。卡布姆。
(顺便说一下,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
FILEs 和iostream
s 混合在一起有点奇怪。)
【讨论】:
【参考方案2】: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';
【讨论】:
fgets
不会修剪终止换行符,因此您必须将其与 fputs
配对,而不是 puts
。
@Zack:谢谢。自从我编写生产 C 代码以来已经有好几年了。【参考方案3】:
编辑:我的预测是错误的,但如果您打算使用流,请阅读以下内容。
另外请考虑使用流(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;
【讨论】:
这可能会发生,但它会为访问冲突提供不同的地址。现在它指向 0x0000000,这意味着程序在某处取消引用 NULL 指针。 @MatteoItalia 直言不讳,我认为这是一个 C 问题,而不是 C++,如果我在上面给出的流实现中仍然存在错误,请告诉我。 我并不是说您的解决方案是错误的,而是您的诊断不正确。 投反对票,因为“char[] 不会以空结尾”是不正确的:fgets
保证如果成功,它将返回一个以空结尾的字符串。
@MatteoItalia 对不起,我之前遇到过严厉的。你是对的,Ferruccio 给出了一个很好的技术答案,我个人仍然会使用流,并且从问题的标记和措辞来看,我认为 OP 打算使用流,但由于某种原因没有。以上是关于C ++读取文件时未处理的异常的主要内容,如果未能解决你的问题,请参考以下文章
错误及异常处理-[PathTooLongException]指定的路径或文件名太长
Pyspark 在读取目录中的所有 parquet 文件时失败,但在单独处理文件时成功
java文件流stream,拷贝复制文件,读取文件,写入文件,及抛出异常的处理