views:

211

answers:

4

Hello all,

I developed a small program which was working fine until I made a really minor change in some unrelated part of the code. From that point onwards the program throws an unhandled win32 exception and Microsoft Visual Studio Just in time debugger kicks in.

I am using codeblocks and my compiler is the gcc compiler. What is frustrating is that the program works fine if I choose to debug from codeblocks with the gdb. This is what does not make sense to me.

Since I can not debug with gdb to see what's wrong (because it runs fine in debugging mode), I put printfs here and there to find the root of it all. I isolated in one function but it just does not make sense.

bool FileReader::readBitmap(int fileNum)
{
char check;
int dataOffset;
int dataSize;
string fileName;

//used for quick int to string conversion
std::ostringstream stringstream;

stringstream<<fileNum;

string fileNumber = stringstream.str();


fileName = "img"+fileNumber+".bmp";

ifstream stream(fileName.c_str(),ios::in|ios::binary);

stream.read(&check,1);

//checking if it is a bitmap file
if(check != 'B')
    return false;
 stream.read(&check,1);
if(check != 'M')
    return false;

stream.seekg(BMPBPP);
stream.read(&check,1);

//if it is not a monochrome bitmap
if(((int)check) != 1)
    return false;//quit


//get the dataoffset
stream.seekg(DATAOFFSET);
stream.read(&check,1);

dataOffset = (int)check;

//get the data size in bytes
stream.seekg(DATASIZEINBYTES);
stream.read(&check,1);

dataSize = (int)check;

//if this is the first image we read
if(firstImageRead)
{
    //allocate the image buffer
    imgBuffer = (char*) malloc(dataSize);

    //and make sure it does not get re-allocated
    firstImageRead = false;
}


//get the actual bitmap data
stream.seekg(dataOffset);
stream.read(imgBuffer,dataSize);


stream.close();
return true;

}

-BIG- EDIT: Trying to find what the problem could be I moved the ifstream from the function to being a private member of the class. And the function now does EXACTLY the same only that it uses stream.open() to open the file.

Now it works with no problems. So the problem lies somehow ... in the ifstream being initialized every time inside the function, as opposed to just being used inside the function. Still ... does not make sense and this should not have occured.

I am really intrigued to find what the problem was here?

Honestly does anyone have any idea what this could be attributed to?

A: 

It would help if you showed the exception and callstack of the failure.

My guess would be there is a sharing violation, you're opening the file again before it was closed. In the cases where you exit early, the file is not being closed.

Frank Schwieterman
The exception is just an Unhandled Win32 Exception with a 4 digit number in square brackets. It is always different.I will do a re-check if I open these kind of files again and forget to close.
Lefteris
EDIT: I commented the stringstream and this time I gave my own name to the image(which exists of course) and I did not get the just in time thingy, but I got a process returned 0xc000005.If memory serves, isn't that something to do with memory access violation?
Lefteris
A: 

Are you sure the file exists and that you are reading from the stream ok?

What about that global 'imgBuffer', make sure nothing is calling free on it between several calls to FileReader::readBitmap()

Hello and thanks for you input, but unfortunately the file does exist and the only time this buffer is freed is at the end of the program. It has to be this function since if I empty it and just return true; , the program runs fine ... but has no input (no file read).

Make sure you are allocating enough space for the buffer. Remember that the malloc() is only called the first time you call this function. If dataSize is say 1000 the first time, and if you on the next file want to read 2000 bytes, dataSize will be 2000, but the buffer is only allocated for 1000 bytes.

Magnus Skog
Hello and thanks for you input, but unfortunately the file does exist and the only time this buffer is freed is at the end of the program. It has to be this function since if I empty it and just return true; , the program runs fine ... but has no input (no file read).
Lefteris
+1  A: 

A few points to investigate:

  • Is firstImageRead initialized to true?
  • The rest of the code doesn't know how big imgBuffer is, so further processing is probably reading beyond the end of the buffer. How does the rest of your code determine how much data to read from imgBuffer?
  • If dataSize of any image is bigger than for the first one, imgBuffer will be too small.
  • If the character you read at position DATASIZEINBYTES happens to be negative, you will try to malloc() about 2GB.

Sidenote: Is it correct, that you read only one byte for the image size? Are the images that small?

sth
Yes , my program assumes that each image will be the same as the first one. It is a neural networks training program, for optical character recognition.So you can say that the first image is the "initializer" image of the network.The imgbuffer's size is known since there is another function which reads that same bitmap to take input such as data Size, dimensions e.t.c.All very valid points though and thanks for taking the time to provide me with advice.
Lefteris
No I don't read only 1 byte.I read datasize bytes from the file. It is all according to the .bmp file format. You can read about it here:http://atlc.sourceforge.net/bmp.html
Lefteris
I meant that you seek to position DATASIZEINBYTES, then read one char (= one byte) to get the size of the image. Since all the fields in the in the .bmp format description you linked to are bigger than one byte, you actually only read a part of the actual datasize value? As far as I can see, the data size in the file format is stored in four bytes.
sth
Thank you, you are actually right, I had assumed that datasize in bytes field occupied a byte, now I saw it was a dword. In my image sizes 8x8 it worked fine and I had not noticed. Thanks for noticing this bug!
Lefteris
A: 

Hello again, I am just answering my own question since I found what the problem was. As most people guessed it was indeed a pointer index going out of bounds by just +1. What made it really hard to spot was that the debugger pointed me to a totally different direction.

That also explains why adding one more private member in the class 'fixed' the problem. It allocated more memory for the fileReader object, and writing out of bounds wrote on the memory occupied by the additional private member and did not cause an unhandled exception.

What do we learn from all this? Be very very careful when setting indices .... since well this is not the first time this happened to me :)

Lefteris