Sign in to follow this  
lonewolff

Problems copying data to an offset with memcpy

Recommended Posts

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

[code] 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);[/code]

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]

Share this post


Link to post
Share on other sites
[quote name='Erik Rufelt' timestamp='1298414632' post='4777737']
[b]&[/b]memblock+sizeof(BITMAPFILEHEADER) shouldn't have the &. :)
[/quote]

Hi Erik, thanks for the reply.

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

[/color][/size][/color][/size] :(

Share this post


Link to post
Share on other sites
[quote name='lonewolff' timestamp='1298414052' post='4777733']
[code]
// Stage 1
memset(&bmfh,0,sizeof(BITMAPFILEHEADER));
memcpy(&bmfh,memblock,sizeof(BITMAPFILEHEADER));
[/code]
[/quote]
Have you read enough to be able to do this memcpy? You should do a check.

[quote]
[code]
// Stage 2
memset(&lpbi,0,sizeof(BITMAPINFOHEADER));
memcpy(&lpbi,&memblock+sizeof(BITMAPFILEHEADER),sizeof(BITMAPINFOHEADER));
[/code]
[/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.

[quote]
[code]
char szBuffer[10];
MessageBox(NULL,itoa(lpbi->bmiHeader.biCompression,szBuffer,10),"",NULL);
[/code]
[/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.

Share this post


Link to post
Share on other sites
[quote]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:
[code]
BITMAPINFO bmi;
memcpy( &bmi, memblock + sizeof(BITMAPFILEHEADER), sizeof( BITMAPINFOHEADER ) );
[/code]

Share this post


Link to post
Share on other sites
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...

[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.
[/quote]

I am aware of this. But, the numbers I am dealing with are 5 characters at max. So, 10 characters is not an issue.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
[quote name='lonewolff' timestamp='1298440433' post='4777845']
[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.
[/quote]

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.

Share this post


Link to post
Share on other sites
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:
[code]
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
}
}
[/code]
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.

[quote]
[color=#1C2837][size=2]What is LPBITMAPINFO used for then?[/quote][/size][/color]
[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).[/size][/color]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this