在解析 STL 时引发未经处理的异常
fgets throwing unhandled exception while parsing stl
我是 c++ 的新手,我正在尝试解析一个大约 64MB 的 stl 文件,其中有大约 ~18K 行。代码在前 100 行工作正常,但随后 fgets 抛出以下异常:
"Unhandled exception at 0x77B0BAC5 (ntdll.dll) in STLparser.exe: 0xC0000024: There is a mismatch between the type of object required by the requested operation and the type of object that is specified in the request."
我已经手动检查了fgets
抛出异常的行,那里没有什么异常。我现在别无选择。任何解决此问题的帮助将不胜感激。
====
============CODE================================#include<fstream>
#include<iostream>
#include"ParseString.h"
#include"Vectors.h"
using namespace std;
int main(void)
{
//Define variables
FILE *file;
char *line = new char;
parsestring oneline;
int n_Vols = 0, n_Elms = 0, n_nods = -1, E = 0;
Nod *nodes = new Nod();
Nod dummy;
Elm *elements = new Elm();
int mycounter = 0;
//Open file
fopen_s(&file, "sample.stl", "r");
while (fgets(line, 1024, file) != NULL) //**********Getting Error Here*************
{
// populate required data
}
fclose(file);
printf("%d,%d,%d", n_Vols, n_Elms, n_nods);
getchar();
return 0;
}
====
===============当损坏时,在此函数上恢复执行(不是我的函数,内部函数(
void __cdecl _unlock (
int locknum
)
{
/*
* leave the critical section.
*/
LeaveCriticalSection( _locktable[locknum].lock );
}
而不是:
char* line = new char;
做:
char[1024] line;
您可能会收到损坏的数据,因为您没有分配任何内存。
char *line = new char;
这会在堆上分配一个字节,并指向它line
。
while (fgets(line, 1024, file) != NULL)
这将最多将 1024 个字节写入 line
指向的位置。 line
只指向一个字节。 这就是你的代码爆炸的原因。
你对单个字符调用fgets,因为你做了:
char *line = new char;
您可能希望分配大小为 1024 的 char 数组
char line[1024] // on the stack
char *line = new char[1024]; // or on the heap
一个问题是这样的:
char *line = new char;
你知道你想做多大的数组,所以需要调用new
。 其次,即使您确实调用了new
,上面的那行也只为 1 个字符分配了空间。
将上述内容更改为:
char line[1024];
因为同样,您确切地知道预先需要多少个字符,只需创建一个该大小的数组即可。
此外,您还可以在其他不需要的地方使用new
:
Nod *nodes = new Nod();
Elm *elements = new Elm();
通常这些错误是由以下人员造成的:
- Java(或类似的语言(程序员,他们错误地认为他们必须使用
new
创建所有对象,或者 - 初学者C++程序员认为在向具有指针参数的函数提供参数时必须声明指针变量并分配内存。 通常只需要传递现有变量的地址(使用
address-of
运算符&
(。
要创建对象,如果对象的生存期在声明它的块的范围内,则只需执行以下操作:
Nod nodes;
Elm elements;
完成此操作后,请使用 .
运算符而不是 ->
来访问 nodes
和 elements
的成员。
另一个问题是,您没有检查对fopen_s
的调用是否因 NULL 文件句柄而失败。 如果使用 NULL 文件句柄调用fgets
,则行为未定义(可能是崩溃(。 在继续之前,请务必检查是否已成功打开文件。
为保存数据的行分配必要的内存空间。
char * fgets ( char * str, int num, FILE * stream );
str指向复制字符串读取的字符数组的指针。
数字要复制到 str 的最大字符数(包括终止空字符(。
在代码中,将 num 设置为 1024,因此您的行应指向分配 1024*char 大小内存空间的位置。因此,您需要将代码修改为:
char *line = new char[1024];
顺便说一句,当您不再需要堆资源时,您应该释放堆资源。
delete nodes;
delete elements;
你有几个正确的答案。 但是,我认为您最好的方法是继续编写C++:
#include <cstdio>
#include <fstream>
#include <string>
#include <vector>
#include "ParseString.h"
#include "Vectors.h"
int main()
{
//Open file
std::ifstream file("sample.stl");
if (file.fail()) {
std::fprintf(stderr, "Unable to open sample.stln");
return 1;
}
int n_Vols = 0, n_Elms = 0, n_nods = -1;
std::string buffer;
while (std::getline(file, buffer)) {
// populate required data
// you can use buffer.c_str() to get a const char*
parsestring oneline;
int E = 0, mycounter = 0;
// based on the name, I suspect you actually want multiple Nod's
std::vector<Nod> nodes;
Nod dummy;
// based on the name, I suspect you actually want multiple Elm's
std::vector<Elm> elements;
...
}
printf("%d,%d,%d", n_Vols, n_Elms, n_nods);
getchar();
return 0;
}
就个人而言,我喜欢std::
,但其他人喜欢您最初使用using namespace std
方法。
我还应该提到,fgets
(和fgets_s
(不会抛出C++例外。 中止程序的方法不止一种,并且无法通过添加try { ... } catch
块来修复您遇到的问题。
遇到段错误,但您可能会触发断言。 您甚至可能会遇到 Windows 结构化异常处理,与名称相反,它与C++异常不同。 你的程序最终会死去,但它会因不同的原因而死机,你必须做不同的事情来处理异常、信号(段错误(或 SEH。
别担心,你最终会知道这些东西是什么;我只是想指出,"神秘死亡"可能是由未捕获的异常引起的,但它可能是由任何其他事情引起的。
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 有没有更好的方法来处理异常? try-catch块真的很丑
- VisualC++ 2010 有没有办法找出有关未处理异常错误的更多详细信息
- 在析构函数内部处理异常(但不抛出)
- C++ 程序中双链表的未处理异常
- 抛出字符但捕获整数:如何处理异常的促销和转化
- C++ 异常处理:异常与 ifstream::failure
- 防止线程在处理异常后在分离时调用 std::terminate()
- 当数字可能超出C++中特定数据类型的范围时如何处理异常?
- 运算符重载时未处理<<异常
- 实验室中0x6BE20E11 (ucrtbased.dll) 的未处理异常.exe: 0xC0000005:访问冲突读取
- objective-C或ObjectiveC++能处理C++异常吗
- 如何处理异常,使我的程序仍然运行
- ImageMagick 的未处理异常
- 类数组大小为的未处理异常
- 尝试将构造函数设置为 0 - c++ 的未处理异常
- C - 处理异常而不会丢失呼叫箱
- 在分配scoped_ptr之前处理异常
- C++异常处理如何处理异常派生类
- Dijkstra 中0x001e1078 s_Algorithm.exe的未处理异常:0xC0000005:访问冲突读取位置0xbaadf00d