views:

61

answers:

2

Hi all,

Does anyone here know of a way a C++ ifstream's get pointer might get corrupted after a read() call? I'm seeing some truly bizarre behaviour that I'm at a loss to explain. For example (illustrative code, rather than what I'm actually running):

int main()
{
   // datafile.bin is a 2MB binary file...
   std::ifstream ifs( "datafile.bin", ios::binary );
   ifs.exceptions ( ifstream::eofbit | ifstream::failbit | ifstream::badbit );

   int data[100];

   std::istream::pos_type current_pos = ifs.tellg();
   // current_pos = 0, as you'd expect...

   ifs.read( reinterpret_cast<char*>(data), 100 * sizeof(int) );
   // throws no exception, so no error bits set...

   std::streamsize bytes_read = ifs.gcount();
   // gives 400, as you'd expect...

   current_pos = ifs.tellg();
   // current_pos = 0x1e1a or something similarly daft

   return 0;
}

My example shows an array read, but it's happened even when reading single values of built-in types; the get pointer before the read is correct, the gcount() call reports the correct number of bytes read, but afterwards the get pointer is completely screwy. This doesn't happen with every read() call - sometimes I get through bunches of them before one stuffs up. What could possibly be monkeying with the get pointer? Am I doing something profoundly stupid?

Any and all help greatly appreciated...

Simon

A: 

Hi SimonC

I tried running your code in VS 2008 on Vista machine, but did not get any error. I have modified your code a bit for printing on console.

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
   // datafile.bin is a 2MB binary file...
   std::ifstream ifs( "H_Line.bmp", ios::binary );
   ifs.exceptions ( ifstream::eofbit | ifstream::failbit | ifstream::badbit );

   int data[100];

   std::istream::pos_type current_pos = ifs.tellg();

   cout<<current_pos<<endl; // current_pos = 0, as mentioned


   ifs.read( reinterpret_cast<char*>(data), 100 * sizeof(int) );
   // throws no exception, so no error bits set...

   std::streamsize bytes_read = ifs.gcount();

   cout<<bytes_read<<endl; // gives 400, as you have mentioned

   current_pos = ifs.tellg();

   cout<<current_pos<<endl; // FOR ME IT IS GIVING 400


   return 0;
}

I have tested this on a BMP image file of size >20 MB

Could you please elaborate which machine/compiler you are using. Thanks

Favonius
@Favonius, to mark up code, just indent it by 4 characters, don't use <pre> html tags.
AProgrammer
Sure, sorry, I should have made clear in the question that this was illustrative code rather than my actual code (which isn't particularly amenable to concise presentation here).FWIW my toolset is VS2010 running on Win7 Professional x64, configuration Win32|Debug.
SimonC
+1  A: 

pos_type isn't an integral type but a class, I'd not try to try to interpret its representation. It is implicitly convertible to an integral type, but if you are looking at it in the debugger, you'll see the internal representation.

AProgrammer
Sure, yes - I'm looking at in in the debugger, so seeing the internal representation, and I'm cross-checking this with my file open in a hex editor as I go. The addresses I'm seeing all check out until suddenly ping! my get pointer is half way down the file despite ifs.gcount() reporting the correct number of bytes read.
SimonC