tags:

views:

86

answers:

3

Hello,

When trying to read tokens from a file in C++, I receive a seg fault. Just to play with some things, I tried reading over the file and just printing and surprisingly if you uncomment the code for the first file read and then read the second file everything works fine. If you leave the commented code commented, you receive the seg fault upon closing the first file. This could be an issue with the library on my school machine... The stack trace is below for the segfault (below the code itself). It's also interesting to note that I do not have to do this 'hack' for each file I open, once the dummy-commented-code has been executed all subsequent streams open just fine.

int main()
{
ifstream myfile1;
ifstream myfile2;

int m; //number of elements in 1st file
int n; //number of elements in 2nd file
int counter = 0;

int x = 0;
int y = 0;
int theta = 0;

Minutiae* minutiae;
minutiae = new Minutiae(x,y,theta,0);

Minutiae* file1_minutiaes;
Minutiae* file2_minutiaes;

int num;

//Some Error is caused with segfault if i Try to fill the minutiae array and then close the file unless i do this first
/*////////////////////
  myfile1.open("2a");


  if (myfile1.is_open())
  {

    counter = 0;

    while (!myfile1.eof() )
    {

     myfile1 >> x >> y >> theta;
     minutiae = new Minutiae(x,y,theta,counter);
     counter++;
    }

    myfile1.close();

  }
  else
  {
  cout << "unable to open file1" << endl;
  return(0);
  }
*/////////////////////////////////////




  myfile1.open("2a");

  if (myfile1.is_open())
  {
    counter = 0;
    myfile1 >> m;

    file1_minutiaes = new Minutiae[m];

    while (!myfile1.eof() )
    {

     myfile1 >> x >> y >> theta;

     //minutiae = new Minutiae(x,y,theta,counter);
     //file1_minutiaes[counter] = *minutiae;
     file1_minutiaes[counter] = *(new Minutiae(x,y,theta,counter));
     counter++;

    }
    myfile1.close();
    cout << "closing file1" << endl;

  }
  else
  {
  cout << "unable to open file1" << endl;
  return(0);
  }

////////////////////////////////
}

And the stack trace:

Starting program: /cs/student/dick_man_chini/Desktop/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x00c47a72 in _int_free () from /lib/libc.so.6
(gdb) up
#1  0x006d9342 in operator delete(void*) () from /usr/lib/libstdc++.so.6
(gdb) up
#2  0x006d939e in operator delete[](void*) () from /usr/lib/libstdc++.so.6
(gdb) up
#3  0x00686130 in std::basic_filebuf<char, std::char_traits<char> >::_M_destroy_internal_buffer() () from /usr/lib/libstdc++.so.6
(gdb) up
#4  0x006874d1 in std::basic_filebuf<char, std::char_traits<char> >::close() () from /usr/lib/libstdc++.so.6
(gdb) up
#5  0x006894a6 in std::basic_ifstream<char, std::char_traits<char> >::close() () from /usr/lib/libstdc++.so.6
(gdb) up
#6  0x08048e96 in main ()
(gdb) up
Initial frame selected; you cannot go up.
(gdb) 

Thanks in advance.

A: 

The common process for reading files:

myfile1.open("2a");
// Note the change in the next line
if (!myfile1)
{
    cout << "unable to open file1" << endl;
    return(0);
}

counter = 0;

// Note, this line differs between the two examples.
myfile1 >> m;

file1_minutiaes = new Minutiae[m];

// Note the change in the following line
while (myfile1 >> x >> y >> theta)
{
    //minutiae = new Minutiae(x,y,theta,counter);
    //file1_minutiaes[counter] = *minutiae;
    file1_minutiaes[counter] = *(new Minutiae(x,y,theta,counter));
    counter++;
}
myfile1.close();
cout << "closing file1" << endl;

I suggest you use a std::vector instead of an array:

  std::vector<Minutiae> file1_minutiaes;

When processing data files, a good idea is to use dynamic containers.

Thomas Matthews
A: 

If m is smaller than the actual number of rows of data in your file, you'll stomp over random memory, quite possibly causing corruption and the crash you're seeing. Your while loop should also make sure than you don't exceed m iterations.

In C++ land however you can use std::vector to manage all your memory for you: Read each line, create a Minutiae on the stack, and then push it onto the vector (alternately use new and store smart pointers of some sort).

Mark B
A: 

A) as mentioned above, your first attempt is actually leaking, as you just have a pointer, instead of an actual array or an array of pointers, since what new is returning is a Minutiae pointer, NOT a Minutiae. Your second attempt is returning a Minutiae pointer, then dereferencing it to get a Minutiae, which is then copied using the assignment operator to the Minutiae created in your array. You might want to read up on pointers just to be sure you understand the differences.

B) first thing I'd do is ensure that your data is formatted absolutely correctly according to your assumptions (integer followed by integer followed by integer * however many rows). After that, you should probably use eof() || bad() instead of just eof(). Or fail I think uses both of them. Look at the reference for an ifstream, but if memory serves me right using just eof will not safeguard you in case reading the file runs into some other error, which could be the cause of your SIGSEV.

foxwoods