Solved

extra bytes

Posted on 2014-03-17
11
280 Views
Last Modified: 2014-03-21
Hi I try to write 8 bit bmp but found that there is some bytes that wasn't be in file.
After 2 bytes BM always appears 2 extra bytes (and they are not empty). I removed almost everything from code to find where is the problem.

 typedef struct  {
      char B;
      char M;
      int width ;//4 bytes
      int height; //4 bytes
       } BMPHEAD;

     BMPHEAD bh;

    bh.B=0x42;
    bh.M=0x77;
   bh.width =819;
    bh.height= 460;
  file.write ((char*)(&bh), sizeof(bh));

Open in new window


but when I open created file in Hex editor I see 12 bytes not 10 as expected. There is 2 extra bytes (byte 3 and 4).
Can any one tell me what's the problem with my code?
snapshot5.png
0
Comment
Question by:mastiSoft
  • 2
  • 2
  • 2
  • +4
11 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39934352
I'm no C++ expert, but don't structures get padded to fit word boundaries?
0
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 39934354
this is due to "padding" of the different byte sizes of the struct parts.

the first 2 being CHAR, each 1 byte, then next ones are int (each 4 bytes), the first 2 bytes are padded with 2 bytes to match ...

so far for the explanation that I remember of my old days in C/C++ ...
not sure about the solution, but I presume you will need some intermediate data structures to solve this ...
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39934379
As an old mainframe assembler programmer... I do remember Fullwords / Halfword etc being important... but didn't think that taken into account in C++... but maybe it still is.

If it is a full word boundary issue, I think the issue would "go away" if you swap the order of the items in your typedef.

typedef struct  {
      int width ;//4 bytes
      int height; //4 bytes
      char B;
      char M;
       } BMPHEAD;
0
 
LVL 32

Expert Comment

by:phoffric
ID: 39934822
Using Ken Butters revision, in Visual Studio, the following code produced sizeB = 12, instead of 10.
   size_t sizeB = sizeof( BMPHEAD );
   printf( "sizeof(BMPHEAD) = %d\n", sizeB);

Open in new window

There are still two bytes of padding at the end of the struct. This allows for arrays of BMPHEAD to be defined and then still have width laid out on a 4-byte boundary. The reason for the alignment in x86 is performance improvements. Some other processor require proper alignment and packing is not permitted.

In general to have a minimal memory footprint for a struct, you put the largest types first (e.g., double) and then the next largest (e.g., float or long), working down to the smallest.

By adding a #pragma pack(1) directive to Visual Studio code, then there was no packing and the size of the struct is 10 on my platform.
0
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39934844
@phoffric --- I think you nailed it exactly. Nice!

In most cases, I'd say you should use the pack directive with extreme prejudice, because you are likely to cause errors on some platforms.... however since it looks like in this case were are dealing with a BMP file which would require a very specific layout... it would be an ideal use of the #pragma pack(1) directive.

again... nice find @Phoffric!
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 33

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 39934928
to add to above comments:

the default alignment of members of a struct or class in c/c++ is 8-bytes for many compilers. that means that a new member with a size of 8-bytes or more always starts at an address that can be divided by 8 without rest. the possible gap to a previous member was padded by zeros.  if the new member was smaller than 8-byte it was aligned according to its size. for a 32-bit integer it means it would be aligned at the next 4-byte boundary. that is what you experienced. because of that, if you order the members by their size, biggest first, it is a good chance that the structure was packed beside you were using 'odd' array sizes or class members with an odd size (see also comments of Ken Butters and phoffric).

also, all compilers and ide's have an option to get structures packed and have no padding then. if using visual c++ you would go to c++ properties of the project and set the property 'Struct Member Alignment' in tab 'Code Generation' to '1 Byte' what would add '/Zp1' to the compiler options. the #pragma pack alternative would move the solution to the source code what could have advantages (for example you could handle it in one header file) or disadvantages (it is not portable and not necessarily the place where other developers would look for it).

Sara
0
 
LVL 24

Accepted Solution

by:
chaau earned 250 total points
ID: 39935468
To add to the Sara's comments above: If you do not want to change the byte alignment for the whole program, but only want to align bytes within the structure use pragma pack directive, like this:
#pragma pack(1) //1 byte alignment
typedef struct  {
      char B;
      char M;
      int width ;//4 bytes
      int height; //4 bytes
       } BMPHEAD;
#pragma pack() // back to the project default alignment

Open in new window

0
 
LVL 1

Author Closing Comment

by:mastiSoft
ID: 39936476
Thank you very much, now it works as it have to .
0
 
LVL 33

Expert Comment

by:sarabande
ID: 39936912
mastiSoft, you probably should spread the points evenly between Ken Butters, phoffric, me and chaau who all have posted valid solutions to your question.

Sara
0
 
LVL 1

Author Comment

by:mastiSoft
ID: 39945126
Yes I will  spread the points evenly between Ken Butters, phoffric and Sara
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now