我是c ++的新手,我正在尝试解析一个大约64MB且大约有18K行的stl文件。代码适用于前几百行,但随后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 );
}
答案 0 :(得分:2)
而不是:
char* line = new char;
执行:
char[1024] line;
由于您没有分配任何内存,您可能会收到损坏的数据。
答案 1 :(得分:1)
char *line = new char;
这会在堆上分配一个字节,并使line
指向它。
while (fgets(line, 1024, file) != NULL)
这会将最多1024个字节写入line
指向的位置。 line
只指向一个字节。这就是你的代码爆炸的原因。
答案 2 :(得分:1)
您应该为保存数据的行分配必要的内存空间。
char * fgets ( char * str, int num, FILE * stream );
<强> STR 强>
指向复制字符串的字符数组的指针。
的 NUM 强>
要复制到str的最大字符数(包括终止空字符)。
,将num设置为1024,所以你的行应指向分配1024 * char size内存空间的位置。因此,您需要将代码修改为:
char *line = new char[1024];
顺便说一句。您应该在不再需要时释放堆资源。
delete nodes;
delete elements;
答案 3 :(得分:1)
你在一个char上调用fgets,因为你做了:
char *line = new char;
您可能希望分配大小为1024的char数组
char line[1024] // on the stack
char *line = new char[1024]; // or on the heap
答案 4 :(得分:1)
一个问题是:
char *line = new char;
您知道要制作数组有多大,因此需要调用new
。其次,即使你打电话给new
,上面那行也只为1个字符分配空间。
将上述内容更改为:
char line[1024];
再次,您确切地知道前面想要多少个字符,只需创建一个大小的数组。
此外,您在其他不需要的地方使用new
:
Nod *nodes = new Nod();
Elm *elements = new Elm();
通常这些错误来自:
new
创建所有对象,或者address-of
运算符&
)。要创建对象,如果对象的生命周期在声明的块的范围内,则这就是必需的:
Nod nodes;
Elm elements;
完成后,请使用.
运算符代替->
来访问nodes
和elements
的成员。
另一个问题是您没有检查对fopen_s
的调用是否因NULL文件句柄而失败。如果使用NULL文件句柄调用fgets
,则行为未定义(可能是崩溃)。在继续之前,请务必检查您是否已成功打开文件。
答案 5 :(得分:1)
你有几个正确的答案。但是,我认为你最好的方法是继续编写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.stl\n");
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。
不用担心,你最终会了解那些东西是什么;我只是想指出,#34;神秘地死亡&#34; 可以是由未捕获的异常引起的,但它可能由许多其他因素引起。