文件I / O中的分段错误

时间:2011-06-03 21:25:46

标签: c++ pointers file-io segmentation-fault fstream

我编写了一个代码来读取文件,将其存储在结构中并显示它。但不知何故,它给了我一个分段错误,我不知道为什么。有人可以帮助我吗?

输出:

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

3 个答案:

答案 0 :(得分:6)

您的lane是一个包含2个元素的数组,但是当您的内循环中的i到达2时,您正在尝试打印a->lane[2][0],而不是{{1}}存在。

答案 1 :(得分: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

为了清楚起见,我添加了括号。

此外,您的程序中存在内存泄漏。应该有deletenew语句,以确保没有内存泄漏。所以写下这些:

delete [] a->roadId;
delete [] a->lane[0];
delete [] a->lane[1];
delete a; //you've written only this!

注意delete a应该是解除内存释放时的最后一条语句!

答案 2 :(得分: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对象然后单独打开它,而是通常计划将名称传递给ctor,以便在单个操作中定义和打开,如:

  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的另一个原因)。

我知道这可能听起来很消极,这让我有点不知所措。一方面,我真的喜欢提出更好的做事方式。与此同时,这看起来很像家庭作业,我非常犹豫不决,只是发布更好的代码。我试图提供一些关于更好方法的提示,但是意识到它们可能没有你想要的那么具体 - 我为此道歉,但鉴于它可能是功课我不认为我可以成为一个更具体。