 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Nafai Guest
|
Posted: Wed Sep 29, 2004 11:56 am Post subject: Problem with structs and mem. allocation |
|
|
Hi. Have a look at this program:
struct tmp {
short a;
int b;
short c;
};
int main()
{
ofstream f("tmp.bin",ios::binary);
tmp t; t.a=5; t.b=2000; t.c=2;
f.write((const char*)&t.a,sizeof(short));
f.write((const char*)&t.b,sizeof(int));
f.write((const char*)&t.c,sizeof(char));
f.close();
ifstream g("tmp.bin", ios::binary);
tmp s;
g.read((char*)&s,sizeof(tmp));
cout << s.a << " " << s.b << " " << s.c << " " << endl;
cout << &s.a << " " << &s.b << " " << &s.c << " " << endl;
g.close();
}
The output should be (supposing &s==0x22fd48):
5 2000 2
0x22fd48 0x22fd4a 0x22fd4e
But the actual output is:
5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50
So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it starts
after 4 bytes. That's why the g.read(...) doesn't work.
I tried:
but: cout << *((int*)((char*) (&s)+sizeof(short)))
and it output 2000.
In conclusion: &s+sizeof(s.a) != &s.b
Is all this my mistake or am I right??? I'm looking forward to an
explanation.
Thanks!
|
|
| Back to top |
|
 |
John Harrison Guest
|
Posted: Wed Sep 29, 2004 12:11 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
"Nafai" <nafai3000 (AT) yahoo (DOT) es> wrote
| Quote: | Hi. Have a look at this program:
struct tmp {
short a;
int b;
short c;
};
int main()
{
ofstream f("tmp.bin",ios::binary);
tmp t; t.a=5; t.b=2000; t.c=2;
f.write((const char*)&t.a,sizeof(short));
f.write((const char*)&t.b,sizeof(int));
f.write((const char*)&t.c,sizeof(char));
f.close();
ifstream g("tmp.bin", ios::binary);
tmp s;
g.read((char*)&s,sizeof(tmp));
cout << s.a << " " << s.b << " " << s.c << " " << endl;
cout << &s.a << " " << &s.b << " " << &s.c << " " << endl;
g.close();
}
The output should be (supposing &s==0x22fd48):
5 2000 2
0x22fd48 0x22fd4a 0x22fd4e
But the actual output is:
5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50
So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it starts
after 4 bytes. That's why the g.read(...) doesn't work.
|
Right. Now what made you think that they had to be contiguous in memory?
| Quote: |
I tried:
but: cout << *((int*)((char*) (&s)+sizeof(short)))
and it output 2000.
In conclusion: &s+sizeof(s.a) != &s.b
Is all this my mistake or am I right??? I'm looking forward to an
explanation.
|
Compilers are allowed to add 'padding' between the data members of a struct
or class. They do this for efficiency reasons. Most compilers will have
compiler specific options to alter the padding or to turn it off entirely.
Alternatively you could read your data in the same way that you wrote it,
that would be the sensible thing to do.
john
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Wed Sep 29, 2004 12:34 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
| Quote: |
But the actual output is:
5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50
So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.
Right. Now what made you think that they had to be contiguous in memory?
|
I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read a
full struct with one instruction.
|
|
| Back to top |
|
 |
John Harrison Guest
|
Posted: Wed Sep 29, 2004 1:11 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
"Nafai" <nafai3000 (AT) yahoo (DOT) es> wrote
| Quote: |
But the actual output is:
5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50
So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.
Right. Now what made you think that they had to be contiguous in memory?
I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read
a
full struct with one instruction.
|
That code is OK providing that you read and write in the same way. Your
mistake was reading one way and writing another. Providing you don't mind
any padding bytes being written out to the file, you can read and write a
whole struct in one go.
And of course any binary read or write is not portable across machines,
compilers, etc. etc.
john
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Wed Sep 29, 2004 1:35 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
Nafai wrote:
| Quote: |
But the actual output is:
5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50
So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.
Right. Now what made you think that they had to be contiguous in memory?
I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read a
full struct with one instruction.
|
Right. Now search the same program and you will find that those programs
also write a struct in one rush
g.write( char*)&s, sizeof(tmp) );
and *never* by writing each struct member individually.
(Except of course when the programmer was aware of the padding issue
and took it into account. But thats rare).
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
Nafai Guest
|
Posted: Wed Sep 29, 2004 6:47 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
I came across this problem when reading a BMP file. I defined a struct for
the header and I got into trouble when reading the whole struct. So I have
to read each element of the header (more than 20) one by one? Isn't there
any easier way?
"Karl Heinz Buchegger" <kbuchegg (AT) gascad (DOT) at> escribió en el mensaje
news:415ABA0B.28A162D0 (AT) gascad (DOT) at...
| Quote: | Nafai wrote:
But the actual output is:
5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50
So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.
Right. Now what made you think that they had to be contiguous in
memory?
I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read
a
full struct with one instruction.
Right. Now search the same program and you will find that those programs
also write a struct in one rush
g.write( char*)&s, sizeof(tmp) );
and *never* by writing each struct member individually.
(Except of course when the programmer was aware of the padding issue
and took it into account. But thats rare).
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
|
| Back to top |
|
 |
Julián Albo Guest
|
Posted: Wed Sep 29, 2004 6:53 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
Nafai wrote:
| Quote: | I came across this problem when reading a BMP file. I defined a struct for
the header and I got into trouble when reading the whole struct. So I have
to read each element of the header (more than 20) one by one? Isn't there
any easier way?
|
Write a file that describes the format of the header, and write a program
that reads this file and generates the code for reading the header.
Of course is more work, but is reusable.
--
Salu2
|
|
| Back to top |
|
 |
John Harrison Guest
|
Posted: Wed Sep 29, 2004 9:33 pm Post subject: Re: Problem with structs and mem. allocation |
|
|
"Nafai" <nafai3000 (AT) yahoo (DOT) es> wrote
| Quote: | I came across this problem when reading a BMP file. I defined a struct for
the header and I got into trouble when reading the whole struct. So I have
to read each element of the header (more than 20) one by one? Isn't there
any easier way?
|
Well to be strictly portable you have to read the file one byte at a time,
not just one field at a time. How do you know that the format of an integer
in the BMP file (say) corresponds to the format of an int in your compiler?
If you don't mind not being portable then you should look at compiler
options or pragmas that will allow you to control the padding in your
struct. Then you can read the whole struct in one go.
john
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|