sizeof(myOwnObject) incorrect

S

Sebastian Fahr

Hey there

I have a problem with my own Objects. I have to write a programm in
school that read objects from a binary file.

This Object has the following structure:

#pragma once

class Sandbox
{
int test1; // 4 Byte
int test2; // 4 Byte
int test3; // 4 Byte
int test4; // 4 Byte
int test5; // 4 Byte
int test6; // 4 Byte
char name[25]; //25 Bytes
// 4 + 4 + 4 + 4 + 4 + 4 + 25 Bytes = 49 Bytes
public:
Sandbox(void);
~Sandbox(void);
};

There are no virtual methods ore anything like that. It's like i posted
above. My problem is, i expected sizeof(Sandbox) = 49, but it is 52 when
I do sizeof(Sandbox). There are 3 Bytes too much.

Any ideas where these 3 Bytes are and how I can remove them?

Sebastian

P.S. Sorry for my bad english, it's not my native language.
 
K

Kai-Uwe Bux

Sebastian said:
Hey there

I have a problem with my own Objects. I have to write a programm in
school that read objects from a binary file.

This Object has the following structure:

#pragma once

class Sandbox
{
int test1; // 4 Byte
int test2; // 4 Byte
int test3; // 4 Byte
int test4; // 4 Byte
int test5; // 4 Byte
int test6; // 4 Byte
char name[25]; //25 Bytes
// 4 + 4 + 4 + 4 + 4 + 4 + 25 Bytes = 49 Bytes
public:
Sandbox(void);
~Sandbox(void);
};

There are no virtual methods ore anything like that. It's like i posted
above. My problem is, i expected sizeof(Sandbox) = 49, but it is 52 when
I do sizeof(Sandbox). There are 3 Bytes too much.

Any ideas where these 3 Bytes are and how I can remove them?

a) Read up on "padding". The compiler is thinking ahead: if you have an
array

SandBox some_array [20]

then the int members should still be aligned properly on word boundaries in
memory. For this reason, the compiler inserts some bytes here and there to
make it happen.

b) The position of those bytes is compiler specific, although I would be
willing to bet that in your case, they are all at the end. Another
alternative would be between test6 and name and you also could have two
bytes there and one at the end. In order to figure that your, consult the
manual for your compiler and run some experiments.


Best

Kai-Uwe Bux
 
V

Victor Bazarov

Sebastian said:
I have a problem with my own Objects. I have to write a programm in
school that read objects from a binary file.

This Object has the following structure:

#pragma once

class Sandbox
{
int test1; // 4 Byte
int test2; // 4 Byte
int test3; // 4 Byte
int test4; // 4 Byte
int test5; // 4 Byte
int test6; // 4 Byte
char name[25]; //25 Bytes
// 4 + 4 + 4 + 4 + 4 + 4 + 25 Bytes = 49 Bytes
public:
Sandbox(void);
~Sandbox(void);
};

There are no virtual methods ore anything like that. It's like i
posted above. My problem is, i expected sizeof(Sandbox) = 49, but it
is 52 when I do sizeof(Sandbox). There are 3 Bytes too much.

Any ideas where these 3 Bytes are and how I can remove them?

It's called "padding". You may be able to remove them by using some
custom alignment instructions to your compiler. They are compiler-
specific, so the standard C++ language does not say what they are or
what they can be.

See if your compiler supports #pragma align, or any other similar
alignment command-line option or pragma. IOW, RTFM.

V
 
P

peter koch

Hey there

I have a problem with my own Objects. I have to write a programm in
school that read objects from a binary file.

This Object has the following structure:

#pragma once

class Sandbox
{
int test1; // 4 Byte
int test2; // 4 Byte
int test3; // 4 Byte
int test4; // 4 Byte
int test5; // 4 Byte
int test6; // 4 Byte
char name[25]; //25 Bytes
// 4 + 4 + 4 + 4 + 4 + 4 + 25 Bytes = 49 Bytes
public:
Sandbox(void);
~Sandbox(void);
You do not need the void here- its a C-ism.
};

There are no virtual methods ore anything like that. It's like i posted
above. My problem is, i expected sizeof(Sandbox) = 49, but it is 52 when
I do sizeof(Sandbox).
Your expectations were wrong. There is often extra padding in classes
- data that is unused. This data is there to assure proper performance
and/or operation of the computer as some data might have to be
properly aligned. Here, there is likely a requirement that an int is
aligned on a 4-byte boundary - an adress that is divisible by four.
The compiler thus adds three bytes to the class which means that you
can have your Sandbox class in an array and still adress e.g. the
second element.

/Peter
 
J

Juha Nieminen

Sebastian said:
I have a problem with my own Objects. I have to write a programm in
school that read objects from a binary file.

Unfortunately you cannot read binary data from a file *directly* into
a struct/class (eg. with a fread command). It's not portable and usually
just doesn't work (because of padding and word alignment reasons).

Usually hardware imposes some limitation on how a struct is organized
in memory. For example, if you have something like this:

struct A
{
int i1; // 4 bytes
char c; // 1 byte
int i2; // 4 bytes
};

you'll probably notice that in a typical 32-bit computer sizeof(A) will
be 12, and that 4 bytes will have been allocated for the char instead of
just 1 byte.

In some hardware this is for optimization (accessing non-word-aligned
integers causes penalties), in other hardware it's mandatory (trying to
access non-word-aligned integers causes a bus error interrupt).

If you had 9 bytes in a binary file and you assumed you could simply
read its content directly into that struct (eg. with fread), it would
just not work.
 
J

Jim Langston

Sebastian Fahr said:
Hey there

I have a problem with my own Objects. I have to write a programm in school
that read objects from a binary file.

This Object has the following structure:

#pragma once

class Sandbox
{
int test1; // 4 Byte
int test2; // 4 Byte
int test3; // 4 Byte
int test4; // 4 Byte
int test5; // 4 Byte
int test6; // 4 Byte
char name[25]; //25 Bytes
// 4 + 4 + 4 + 4 + 4 + 4 + 25 Bytes = 49 Bytes
public:
Sandbox(void);
~Sandbox(void);
};

There are no virtual methods ore anything like that. It's like i posted
above. My problem is, i expected sizeof(Sandbox) = 49, but it is 52 when I
do sizeof(Sandbox). There are 3 Bytes too much.

Any ideas where these 3 Bytes are and how I can remove them?

Sebastian

P.S. Sorry for my bad english, it's not my native language.

As other people are stating, it's from alignment issues. It appears your
compiler/os is 4 byte aligned for integers. Intergers need to start on a 4
byte boundary. Consider if you had the class:

class Foo
{
int MyInt;
char MyChar;
};

MyInt would be aligned to a 4 byte boundary, such as 4000 (hypothetical).
MyChar would then take up the next byte. So 4000 - 4003 would be MyInt,
MyChar would be in 4004. Now what if you had an array of 2 of these? Foo
Data[2]; Data[1] without padding would start on 4005. But 4005 is not 4
byte aligned. So the compiler adds padding bytes, unused bytes, at the end
of the array so in effect it becomes:

class Foo
{
int MyInt;
char MyChar;
char unused[3];
};

so now Data[1] would start on a 4 byte boundary. And that's what you're
seeing with sizeof.

There are a few ways to deal with this. The common way is serialization.
Read each data into each variable.
pseudo code since I don't use fread and dont' even know the syntax:

fread( myfile, MyInstance.test1, sizeof( MyInstance.test1 ) );
fread( myfile, MyInstance.test1, sizeof( MyInstance.test2 ) );
etc...
Read each part of the structure/class individually.

Another method that is sometimes used (but not encouraged) is to write and
read the same structure. So you'd write a Foo (with thepadding) and read it
back in but since the written structure had the padding so will the read and
it'll line up. This can work sometimes, but when you're getting a file from
an external source (such as you are) you can't really do that.

Yet another method is to kludge. Find out where the padding is, see if it
effects you and if it doesn't, read all but hte padding. Ugly, prone to
errors and crashes and a kludge, not a fix.

fread( myfile, MyInstance, sizeof( MyInstance ) - 3 );
or manually put the nubmer of bytes
fread( myfile, MyInstance, 49 );

This is ugly, and although you may be attempted to use it, your teacher
probably wouldn't accept it anwyay. What happens when you add another char
to the data? You're going to have to search your code for the "magic
numbers" 3 or 49 and figure out what they should be. :Don't do it.

Yet another way is some compilers have a #pragma or a command line switch to
turn packing off. Suce as one compiler uses:

#pragma pack(0)

saying don't use packing bytes. Although this can work, it is platform/OS
dependant and won't work on other platforms. Also, it can slow down some
computers as it has to fiddle intergers around in the CPU to line them up
right. Some CPUs will jsut plain crash when they try to use an unaligned
int.

So, what are your optoins? Well, I think I've listed them all, but the one I
would suggest is serialization.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,124
Latest member
JuniorPell
Top