Problems copying data to an offset with memcpy

Started by
8 comments, last by rip-off 13 years, 1 month ago
Hi Guys,

I am having problems with copying data to an offset.

To start I'll show you my code and explain what I am doing

ifstream file ("c:\\test.bmp",ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size=file.tellg();
memblock=new char[size];
file.seekg(0,ios::beg);
file.read(memblock,size);
file.close();
}
else
{
MessageBox(NULL,"Unable to open file","Unable to open file",NULL);
SetFocus(hWnd);
PostQuitMessage(0);
return 0;
}

// Stage 1
memset(&bmfh,0,sizeof(BITMAPFILEHEADER));
memcpy(&bmfh,memblock,sizeof(BITMAPFILEHEADER));

// Stage 2
memset(&lpbi,0,sizeof(BITMAPINFOHEADER));
memcpy(&lpbi,&memblock+sizeof(BITMAPFILEHEADER),sizeof(BITMAPINFOHEADER));

char szBuffer[10];
MessageBox(NULL,itoa(lpbi->bmiHeader.biCompression,szBuffer,10),"",NULL);


I am loading a bitmap into memory (with a header (BITMAPFILEHEADER) of 14 bytes).

The header is copied from 'memblock' to the 'bmfh' struct. At this point, with a bit of debugging, the results are correct.

I am then trying to copy the next 40 bytes into an LPBITMAPINFO struct from 'memblock + 14 (the size of BITMAPFILEHEADER).

But from this point the results are corrupted. Where 'lpbi->bmiHeader.biCompression' should be set to 0, the result is random every time.

Is the way I am using memcpy wrong?

Any help would be awesome as I am pretty 'debugged' out :D


[Edit]
The bitmap I am using is correct and had a 14 byte BITMAPFILEHEADER, has 40 bytes of LPBITMAPINFO, and is data after that point.
[/edit]
Advertisement
&memblock+sizeof(BITMAPFILEHEADER) shouldn't have the &. :)

&memblock+sizeof(BITMAPFILEHEADER) shouldn't have the &. :)


Hi Erik, thanks for the reply.

When I try without the &, I then get an access violation when I call [color="#008000"][color="#008000"]MessageBox(NULL,itoa(lpbi->bmiHeader.biCompression,szBuffer,10),"",NULL);

:(


// Stage 1
memset(&bmfh,0,sizeof(BITMAPFILEHEADER));
memcpy(&bmfh,memblock,sizeof(BITMAPFILEHEADER));


Have you read enough to be able to do this memcpy? You should do a check.



// Stage 2
memset(&lpbi,0,sizeof(BITMAPINFOHEADER));
memcpy(&lpbi,&memblock+sizeof(BITMAPFILEHEADER),sizeof(BITMAPINFOHEADER));

[/quote]
Same again. And in addition to what Erik said, I suspect lpbi is already a pointer if you're using MS-style Hungarian notation. So you probably don't want to take the address of the first arguments here, either.



char szBuffer[10];
MessageBox(NULL,itoa(lpbi->bmiHeader.biCompression,szBuffer,10),"",NULL);

[/quote]
10 chars isn't enough to fit the representation for all 32 bit integral values when written in base 10 and with a nul terminator included.
I am then trying to copy the next 40 bytes into an LPBITMAPINFO struct [/quote]
Maybe you're just not using the correct terms, but LPBITMAPINFO is a pointer, not a structure. Do you, in fact mean:

BITMAPINFO bmi;
memcpy( &bmi, memblock + sizeof(BITMAPFILEHEADER), sizeof( BITMAPINFOHEADER ) );

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Hi Buckeye,

That was the cause of the problem. I was using LPBITMAPINFO. Changing it to BITMAPINFO did the job.

What is LPBITMAPINFO used for then?

Thanks again! B)


Also...


10 chars isn't enough to fit the representation for all 32 bit integral values when written in base 10 and with a nul terminator included.


I am aware of this. But, the numbers I am dealing with are 5 characters at max. So, 10 characters is not an issue.
LPBITMAPINFO is a long pointer to a BITMAPINFO structure (um... not sure about "long", but the notation implies it at least).

if you don't know th difference between values/objects and pointers, then I suggest you do go back to that topic...
[size="1"](and if you write that tutorial in the signature, then I suggest you not to...)
[size="1"](what's wrong with the tutorials in my signature?)

[quote name='edd²' timestamp='1298418738' post='4777760']
10 chars isn't enough to fit the representation for all 32 bit integral values when written in base 10 and with a nul terminator included.


I am aware of this. But, the numbers I am dealing with are 5 characters at max. So, 10 characters is not an issue.
[/quote]
Not necessarily. A corrupt (or maliciously constructed) file may crash your application or even open it up to attack.
Why are you reading into a buffer and then copying into the structures? If you read directly into the structures you save yourself some hassle. This also allows you to wait until you have enough information to allocate the bitmap data in a buffer of exactly the right size (you have to be careful about potential buffer based errors due to corrupt or malicious header information.

You can write a helper function to simplify:

template< typename Pod>
bool read(Pod &data, std::istream &in)
{
char *pointer = reinterpret_cast<char *>(&data);
int bytes = sizeof(data);
bool success = in.read(pointer, bytes);
return success && (in.gcount() == bytes);
}

int main()
{
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;


std::ifstream in(...);


if(read(in, fileHeader) && read(in, infoHeader))
{
// do stuff
}
else
{
// complain
}
}

Consider using std::vector<char> instead of raw memory management for such dynamic buffers.

I don't have time to review your tutorials but based on this thread I would estimate that you do not have enough experience to write robust, correct tutorial code.


[color=#1C2837][size=2]What is LPBITMAPINFO used for then?[/quote]
[color=#1C2837][size=2]A typedef for when pointers are required in function signatures. LP means "long pointer", or essentially a "far pointer" which is all but irrelevant nowadays. When you want to store something, use the structure name WHATEVER. If you want to manipulate one, you can use the LPWHATEVER (e.g. you pass the BITMAP info to a function).

This topic is closed to new replies.

Advertisement