文件I/O中的分段错误
我已经编写了一个代码来读取文件,将其存储在一个结构中并只显示它。但不知何故,它给了我一个分段错误,我不知道为什么。有人可以帮帮我吗?文件I/O中的分段错误
输出:
file: /home/neel/map2.txt
file opened
Start Intersection
a->road: 4
a->roadId[0]: 1
a->lane[0][0]: 2
a->lane[0][1]: 2
a->roadId[1]: 2
a->lane[1][0]: 2
a->lane[1][1]: 2
a->roadId[2]: 3
Segmentation fault
代码:
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace std;
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
cout<<"file opened"<<endl;
while (!file.eof())
{
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
cout<<"Intersection inserted"<<endl;
delete a;
}
}
文本文件:
4
1
2
2
2
2
2
3
2
2
4
2
2
你lane
是2个元件的阵列,然而,当i
在内部循环达到2
您正在尝试打印a->lane[2][0]
,这不存在。
啊,我明白了。我犯了一个愚蠢的错误。它应该是文件>>车道[0] [我]而不是文件>>车道[我] [0] ..感谢您的帮助。 – 2011-06-03 21:34:30
file>>a->lane[i][0]; //wrong
file>>a->lane[i][1]; //wrong
该指数应反向:
file>>(a->lane[0][i]); //correct
file>>(a->lane[1][i]); //correct
我加了括弧只是清晰度。
此外,程序中有内存泄漏。应该有尽可能多的delete
,因为有new
语句,以确保没有内存泄漏。所以写下这些:
delete [] a->roadId;
delete [] a->lane[0];
delete [] a->lane[1];
delete a; //you've written only this!
注意delete a
应该是释放内存时的最后一条语句!
非常感谢您指出这个错误.. :) – 2011-06-05 04:12:10
我不是故意的,但是这个代码有足够的问题,几乎很难决定从哪个开始。
using namespace std;
这是第一个红旗。关于我所能说的是,using namespace std;
是一个可怜的主意。与其他命名空间可以接受,但是std
,它应该始终避免(IMO)。
struct Intersection
{
unsigned short road;
long long int *roadId;
short *lane[2];
};
这让我觉得这是一个设计相当糟糕的结构。 std::vector
是一件好事。用它。您可能需要考虑为您的结构类型定义operator>>
,而不仅仅是一个愚蠢的数据结构,所以您可以直接阅读。即使你不这样做,从你使用它的方式,你真正需要的是更多的东西一样:
struct road {
long long Id;
short lane[2];
};
struct Intersection {
int road_count;
road *roads;
};
然后,而不是几个平行阵列的所有相同的尺寸必须平行走,你会得到许多道路,每条道路都有自己的数据。尽管如此,std::vector
仍然更好。
int main(int argc, char** argv)
{
std::ifstream file;
cout<<"file: "<<argv[1]<<endl;
file.open(argv[1], std::ios::in);
而不是定义一个ifstream的对象,然后分别打开它,你应该通常计划上传递名称的构造函数,所以它定义在一个操作中打开,是这样的:
std::ifstream file(argv[1]);
但是,你也通常要添加一些错误检查,所以你只尝试使用命令行参数为文件名,如果一个已经过去了,这样的事情:
if (argc < 2) {
std::cerr << "Usage: your_command <filename>\n";
return EXIT_FAILURE;
}
然后你会有代码来定义ifstream
。
while (!file.eof())
这是另一个主要问题。这种形式的循环基本上总是错误的(包括这种情况,从外观上看)。
cout<<"Start Intersection"<<endl;
Intersection *a = new Intersection;
似乎没有理由动态分配它。你是否也许正在恢复(或者不恢复)Java或C#程序员? Java要求动态地分配用户定义的类的所有对象,但C++不会。
file>>a->road;
a->roadId = new long long int[a->road];
a->lane[0] = new short[a->road];
a->lane[1] = new short[a->road];
cout<<"a->road: "<<a->road<<endl;
for (int i=0; i<a->road; i++)
{
file>>a->roadId[i];
cout<<endl<<"a->roadId["<<i<<"]: "<<a->roadId[i]<<endl;
file>>a->lane[i][0];
cout<<"a->lane["<<i<<"][0]: "<<a->lane[i][0]<<endl;
file>>a->lane[i][1];
cout<<"a->lane["<<i<<"][1]: "<<a->lane[i][1]<<endl;
}
我宁愿单独从显示数据的代码中读取数据的代码。除了作业(或调试)之外,您在阅读时很少要显示大量原始数据。在任何情况下,读取代码通常应该存在于该类别的operator>>
中,以及该类别的operator<<
中的显示代码。
cout<<"Intersection inserted"<<endl;
这似乎是一个彻头彻尾的谎言。你实际上没有插入Intersection
任何东西。
delete a;
当您退出动态分配Intersection
,你就可以消除这一点。如果您坚持要手动处理所有动态分配,则需要在此之前删除组件,以避免发生内存泄漏(另一个原因更喜欢std::vector
)。
我知道这听起来很负面,这让我有点撕裂。一方面,我真的像建议更好的方法来做事情。同时,这看起来足够像作业,我非常犹豫,只是发布更好的代码。我试图提供一些有关更好方法的提示,但意识到它们可能不是特定的 - 我为此道歉,但考虑到这可能是作业,我认为我不能成为一名作家很多更具体。
感谢您的详细评论,我非常感谢。我将我的实际代码简化为此代码,以突出显示问题。我的实际代码非常复杂,包括数据结构。我不需要在这里动态分配内存,但是在我的代码中没有其他选择。我在编程方面有很多经验,但一段时间以来一直处于失控状态,因此编程风格很糟糕。你指出的大部分内容已经被合并到我的代码中,当我试图减少代码长度时,这些代码已经被嵌入到了我的代码中。非常感谢您的帮助。 – 2011-06-05 04:10:39
file >> a-> lane [i] [0]; 这看起来不对。 a-> lane是一个二维数组,其中第一个索引是0或1,第二个索引是从0 - >#道路(-1) – Joe 2011-06-03 21:33:20