2011-06-03 46 views
1

我已经编写了一个代码来读取文件,将其存储在一个结构中并只显示它。但不知何故,它给了我一个分段错误,我不知道为什么。有人可以帮帮我吗?文件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 
+0

file >> a-> lane [i] [0]; 这看起来不对。 a-> lane是一个二维数组,其中第一个索引是0或1,第二个索引是从0 - >#道路(-1) – Joe 2011-06-03 21:33:20

回答

6

lane是2个元件的阵列,然而,当i在内部循环达到2您正在尝试打印a->lane[2][0],这不存在。

+0

啊,我明白了。我犯了一个愚蠢的错误。它应该是文件>>车道[0] [我]而不是文件>>车道[我] [0] ..感谢您的帮助。 – 2011-06-03 21:34:30

2
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应该是释放内存时的最后一条语句!

+0

非常感谢您指出这个错误.. :) – 2011-06-05 04:12:10

2

我不是故意的,但是这个代码有足够的问题,几乎很难决定从哪个开始。

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)。

我知道这听起来很负面,这让我有点撕裂。一方面,我真的建议更好的方法来做事情。同时,这看起来足够像作业,我非常犹豫,只是发布更好的代码。我试图提供一些有关更好方法的提示,但意识到它们可能不是特定的 - 我为此道歉,但考虑到这可能是作业,我认为我不能成为一名作家很多更具体。

+0

感谢您的详细评论,我非常感谢。我将我的实际代码简化为此代码,以突出显示问题。我的实际代码非常复杂,包括数据结构。我不需要在这里动态分配内存,但是在我的代码中没有其他选择。我在编程方面有很多经验,但一段时间以来一直处于失控状态,因此编程风格很糟糕。你指出的大部分内容已经被合并到我的代码中,当我试图减少代码长度时,这些代码已经被嵌入到了我的代码中。非常感谢您的帮助。 – 2011-06-05 04:10:39