Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > What's wrong with this code ? (struct serialization to raw memoryblock)

Reply
Thread Tools

What's wrong with this code ? (struct serialization to raw memoryblock)

 
 
Alfonso Morra
Guest
Posts: n/a
 
      10-03-2005
Hi,

I am at the end of my tether now - after spending several days trying to
figure how to do this. I have finally written a simple "proof of
concept" program to test serializing a structure containing pointers
into a "flattened" bit stream.

Here is my code (it dosen't work - compiles fine, pack appears to work,
but unpack retrieves jibberish and causes program to crash).

I would be grateful for any feedback that helps fix this. My intention
is to build on this example, and use the ideas here, to be able to
persist any data structure (I'll write different pack/unpack routines
for different data stuctures, just to keep things simple). Anyway,
here's the code:


#include "stdlib.h"
#include "stdio.h"
#include "string.h"


typedef struct {
int l ;
double d ;
char* s; /* Null terminated string */
} MyStruct ;


void * pack(size_t *size, MyStruct* m);
MyStruct *unpack(void* block);


int main(int argc, char* argv[]) {

MyStruct *in = (MyStruct*)malloc(sizeof(*in)), *out = NULL;
unsigned char *memblock = NULL ;
size_t size ;

in->l = 1000 ;
in->d = 3.142857;
in->s = strdup("Simple Text" );

memblock = (unsigned char*)pack(&size, in) ;
out = unpack(memblock) ;

printf("Int member has value : %d (expected : %d)", out->l, in->l ) ;
printf("Double member has value : %f (expected : %f)", out->d, in->d ) ;
printf("Int member has value : %s (expected : %s)", out->s, in->s ) ;

free(in->s) ;
free(in) ;
free(out->s) ;
free(out) ;

}




void * pack(size_t *size, MyStruct* m) {
unsigned char *buff = NULL ;
size_t len, length ;

length = strlen(m->s) ;
len = sizeof(int) + sizeof(double) + sizeof(size_t) +
(length+1)*sizeof(char) ;
buff = (unsigned char*)malloc(len) ;

/*copy int*/
memmove(buff, &(m->l), sizeof(int)) ;
/*copy double*/
memmove(buff + sizeof(int), &(m->d), sizeof(double)) ;
/*store length of string*/
memmove(buff + sizeof(int) + sizeof(int), &length, sizeof(size_t));
/*copy string*/
memmove(buff + sizeof(int) + sizeof(double), m->s,
(length+1)*sizeof(char)) ;

*size = len ;
return buff ;
}


MyStruct *unpack(void* block) {
int l, len ;
double d ;
char * s = NULL ;
MyStruct *p = NULL ;

/* get int*/
memmove(&l, block, sizeof(int)) ;
/* get double*/
memmove(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
/* get string length*/
memmove(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
sizeof(size_t)) ;
/* get string*/
s = (char*)malloc(len+1) ;
memmove(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
sizeof(size_t),len) ;

p = (MyStruct*)malloc(sizeof(*p)) ;

p->l = l ;
p->d = d ;
p->s = s ;

/* free resource */
free(block) ;
block = NULL ;
return p ;
}

 
Reply With Quote
 
 
 
 
David Hilsee
Guest
Posts: n/a
 
      10-03-2005

"Alfonso Morra" <(E-Mail Removed)> wrote in message
news:dhr7e9$668$(E-Mail Removed)-infra.bt.com...
> Hi,
>
> I am at the end of my tether now - after spending several days trying to
> figure how to do this. I have finally written a simple "proof of
> concept" program to test serializing a structure containing pointers
> into a "flattened" bit stream.
>
> Here is my code (it dosen't work - compiles fine, pack appears to work,
> but unpack retrieves jibberish and causes program to crash).
>
> I would be grateful for any feedback that helps fix this. My intention
> is to build on this example, and use the ideas here, to be able to
> persist any data structure (I'll write different pack/unpack routines
> for different data stuctures, just to keep things simple). Anyway,
> here's the code:
>
>
> #include "stdlib.h"
> #include "stdio.h"
> #include "string.h"
>
>
> typedef struct {
> int l ;
> double d ;
> char* s; /* Null terminated string */
> } MyStruct ;
>
>
> void * pack(size_t *size, MyStruct* m);
> MyStruct *unpack(void* block);
>
>
> int main(int argc, char* argv[]) {
>
> MyStruct *in = (MyStruct*)malloc(sizeof(*in)), *out = NULL;
> unsigned char *memblock = NULL ;
> size_t size ;
>
> in->l = 1000 ;
> in->d = 3.142857;
> in->s = strdup("Simple Text" );
>
> memblock = (unsigned char*)pack(&size, in) ;
> out = unpack(memblock) ;
>
> printf("Int member has value : %d (expected : %d)", out->l, in->l ) ;
> printf("Double member has value : %f (expected : %f)", out->d, in->d ) ;
> printf("Int member has value : %s (expected : %s)", out->s, in->s ) ;
>
> free(in->s) ;
> free(in) ;
> free(out->s) ;
> free(out) ;
>
> }
>
>
>
>
> void * pack(size_t *size, MyStruct* m) {
> unsigned char *buff = NULL ;
> size_t len, length ;
>
> length = strlen(m->s) ;
> len = sizeof(int) + sizeof(double) + sizeof(size_t) +
> (length+1)*sizeof(char) ;
> buff = (unsigned char*)malloc(len) ;
>
> /*copy int*/
> memmove(buff, &(m->l), sizeof(int)) ;
> /*copy double*/
> memmove(buff + sizeof(int), &(m->d), sizeof(double)) ;
> /*store length of string*/
> memmove(buff + sizeof(int) + sizeof(int), &length, sizeof(size_t));


memmove(buff + sizeof(int) + sizeof(double), &length, sizeof(size_t));

> /*copy string*/
> memmove(buff + sizeof(int) + sizeof(double), m->s,
> (length+1)*sizeof(char)) ;


memmove(buff + sizeof(int) + sizeof(double) + sizeof(size_t), m->s,
(length+1)*sizeof(char)) ;

> *size = len ;
> return buff ;
> }
>
>
> MyStruct *unpack(void* block) {
> int l, len ;
> double d ;
> char * s = NULL ;
> MyStruct *p = NULL ;
>
> /* get int*/
> memmove(&l, block, sizeof(int)) ;
> /* get double*/
> memmove(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
> /* get string length*/
> memmove(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
> sizeof(size_t)) ;
> /* get string*/
> s = (char*)malloc(len+1) ;
>
> memmove(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
> sizeof(size_t),len) ;


memmove(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
sizeof(size_t),len+1) ;

> p = (MyStruct*)malloc(sizeof(*p)) ;
>
> p->l = l ;
> p->d = d ;
> p->s = s ;
>
> /* free resource */
> free(block) ;
> block = NULL ;
> return p ;
> }


BTW, I don't see any reason to prefer memmove() to memcpy().

--
David Hilsee


 
Reply With Quote
 
 
 
 
Alfonso Morra
Guest
Posts: n/a
 
      10-03-2005


David Hilsee wrote:

> "Alfonso Morra" <(E-Mail Removed)> wrote in message
> news:dhr7e9$668$(E-Mail Removed)-infra.bt.com...
>
>>Hi,
>>
>>I am at the end of my tether now - after spending several days trying to
>>figure how to do this. I have finally written a simple "proof of
>>concept" program to test serializing a structure containing pointers
>>into a "flattened" bit stream.
>>
>>Here is my code (it dosen't work - compiles fine, pack appears to work,
>>but unpack retrieves jibberish and causes program to crash).
>>
>>I would be grateful for any feedback that helps fix this. My intention
>>is to build on this example, and use the ideas here, to be able to
>>persist any data structure (I'll write different pack/unpack routines
>>for different data stuctures, just to keep things simple). Anyway,
>>here's the code:
>>
>>
>>#include "stdlib.h"
>>#include "stdio.h"
>>#include "string.h"
>>
>>
>>typedef struct {
>>int l ;
>>double d ;
>>char* s; /* Null terminated string */
>>} MyStruct ;
>>
>>
>>void * pack(size_t *size, MyStruct* m);
>>MyStruct *unpack(void* block);
>>
>>
>>int main(int argc, char* argv[]) {
>>
>>MyStruct *in = (MyStruct*)malloc(sizeof(*in)), *out = NULL;
>>unsigned char *memblock = NULL ;
>>size_t size ;
>>
>>in->l = 1000 ;
>>in->d = 3.142857;
>>in->s = strdup("Simple Text" );
>>
>>memblock = (unsigned char*)pack(&size, in) ;
>>out = unpack(memblock) ;
>>
>>printf("Int member has value : %d (expected : %d)", out->l, in->l ) ;
>>printf("Double member has value : %f (expected : %f)", out->d, in->d ) ;
>>printf("Int member has value : %s (expected : %s)", out->s, in->s ) ;
>>
>>free(in->s) ;
>>free(in) ;
>>free(out->s) ;
>>free(out) ;
>>
>>}
>>
>>
>>
>>
>>void * pack(size_t *size, MyStruct* m) {
>>unsigned char *buff = NULL ;
>>size_t len, length ;
>>
>>length = strlen(m->s) ;
>>len = sizeof(int) + sizeof(double) + sizeof(size_t) +
>>(length+1)*sizeof(char) ;
>>buff = (unsigned char*)malloc(len) ;
>>
>>/*copy int*/
>>memmove(buff, &(m->l), sizeof(int)) ;
>>/*copy double*/
>>memmove(buff + sizeof(int), &(m->d), sizeof(double)) ;
>>/*store length of string*/
>>memmove(buff + sizeof(int) + sizeof(int), &length, sizeof(size_t));

>
>
> memmove(buff + sizeof(int) + sizeof(double), &length, sizeof(size_t));
>
>
>>/*copy string*/
>>memmove(buff + sizeof(int) + sizeof(double), m->s,
>>(length+1)*sizeof(char)) ;

>
>
> memmove(buff + sizeof(int) + sizeof(double) + sizeof(size_t), m->s,
> (length+1)*sizeof(char)) ;
>
>
>>*size = len ;
>>return buff ;
>>}
>>
>>
>>MyStruct *unpack(void* block) {
>>int l, len ;
>>double d ;
>>char * s = NULL ;
>>MyStruct *p = NULL ;
>>
>>/* get int*/
>>memmove(&l, block, sizeof(int)) ;
>>/* get double*/
>>memmove(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
>>/* get string length*/
>>memmove(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
>>sizeof(size_t)) ;
>>/* get string*/
>>s = (char*)malloc(len+1) ;
>>
>>memmove(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
>>sizeof(size_t),len) ;

>
>
> memmove(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
> sizeof(size_t),len+1) ;
>
>
>>p = (MyStruct*)malloc(sizeof(*p)) ;
>>
>>p->l = l ;
>>p->d = d ;
>>p->s = s ;
>>
>>/* free resource */
>>free(block) ;
>>block = NULL ;
>>return p ;
>>}

>
>
> BTW, I don't see any reason to prefer memmove() to memcpy().
>


Many, many thanks David - your help is much appreciated !

 
Reply With Quote
 
Greg
Guest
Posts: n/a
 
      10-03-2005
Alfonso Morra wrote:
> Hi,
>
> I am at the end of my tether now - after spending several days trying to
> figure how to do this. I have finally written a simple "proof of
> concept" program to test serializing a structure containing pointers
> into a "flattened" bit stream.
>
> Here is my code (it dosen't work - compiles fine, pack appears to work,
> but unpack retrieves jibberish and causes program to crash).
>
> I would be grateful for any feedback that helps fix this. My intention
> is to build on this example, and use the ideas here, to be able to
> persist any data structure (I'll write different pack/unpack routines
> for different data stuctures, just to keep things simple). Anyway,
> here's the code:
>
>
> #include "stdlib.h"
> #include "stdio.h"
> #include "string.h"
>
>
> typedef struct {
> int l ;
> double d ;
> char* s; /* Null terminated string */
> } MyStruct ;
>
>
> void * pack(size_t *size, MyStruct* m);
> MyStruct *unpack(void* block);
>
>
> int main(int argc, char* argv[]) {
>
> MyStruct *in = (MyStruct*)malloc(sizeof(*in)), *out = NULL;
> unsigned char *memblock = NULL ;
> size_t size ;
>
> in->l = 1000 ;
> in->d = 3.142857;
> in->s = strdup("Simple Text" );
>
> memblock = (unsigned char*)pack(&size, in) ;
> out = unpack(memblock) ;
>
> printf("Int member has value : %d (expected : %d)", out->l, in->l ) ;
> printf("Double member has value : %f (expected : %f)", out->d, in->d ) ;
> printf("Int member has value : %s (expected : %s)", out->s, in->s ) ;
>
> free(in->s) ;
> free(in) ;
> free(out->s) ;
> free(out) ;
>
> }
>
>
>
>
> void * pack(size_t *size, MyStruct* m) {
> unsigned char *buff = NULL ;
> size_t len, length ;
>
> length = strlen(m->s) ;
> len = sizeof(int) + sizeof(double) + sizeof(size_t) +
> (length+1)*sizeof(char) ;
> buff = (unsigned char*)malloc(len) ;
>
> /*copy int*/
> memmove(buff, &(m->l), sizeof(int)) ;
> /*copy double*/
> memmove(buff + sizeof(int), &(m->d), sizeof(double)) ;
> /*store length of string*/
> memmove(buff + sizeof(int) + sizeof(int), &length, sizeof(size_t));
> /*copy string*/
> memmove(buff + sizeof(int) + sizeof(double), m->s,
> (length+1)*sizeof(char)) ;
>
> *size = len ;
> return buff ;
> }
>
>
> MyStruct *unpack(void* block) {
> int l, len ;
> double d ;
> char * s = NULL ;
> MyStruct *p = NULL ;
>
> /* get int*/
> memmove(&l, block, sizeof(int)) ;
> /* get double*/
> memmove(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
> /* get string length*/
> memmove(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
> sizeof(size_t)) ;
> /* get string*/
> s = (char*)malloc(len+1) ;
> memmove(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
> sizeof(size_t),len) ;
>
> p = (MyStruct*)malloc(sizeof(*p)) ;
>
> p->l = l ;
> p->d = d ;
> p->s = s ;
>
> /* free resource */
> free(block) ;
> block = NULL ;
> return p ;
> }


The members of a struct are not necessarily packed into the smallest
space that will hold them. Usually the compiler will place the
larger-sized elements at 4 or 8 or even 16 byte offsets and insert
bytes to "pad" the space between fields of a struct if necessary. Using
"sizeof" to calculate the field offsets is not reliable or likely even
to be correct. There is an "offset" macro that will report the actual
offset of a field in a struct by substracting the address of the struct
from the address of the field. But then the routine to unpack the data
must be compiled with the same alignment settings as the program that
packed the data, and that is not a safe assumption to make either.

Alternately, you just use a BER (ASN.1) library to encode the data. And
then there is always XML to encode the data in a very portable format.

Greg

 
Reply With Quote
 
Alfonso Morra
Guest
Posts: n/a
 
      10-03-2005


Greg wrote:

>
>
> The members of a struct are not necessarily packed into the smallest
> space that will hold them. Usually the compiler will place the
> larger-sized elements at 4 or 8 or even 16 byte offsets and insert
> bytes to "pad" the space between fields of a struct if necessary. Using
> "sizeof" to calculate the field offsets is not reliable or likely even
> to be correct. There is an "offset" macro that will report the actual
> offset of a field in a struct by substracting the address of the struct
> from the address of the field. But then the routine to unpack the data
> must be compiled with the same alignment settings as the program that
> packed the data, and that is not a safe assumption to make either.
>
> Alternately, you just use a BER (ASN.1) library to encode the data. And
> then there is always XML to encode the data in a very portable format.
>
> Greg
>


Ok, now you've got me worried ...

I can't use XML. Could you please shed some light on BER (never heard of
it) and offset. How would you modify the code (just a couple of lines to
show the concept) to use the more correct offset macro ?

thanks

 
Reply With Quote
 
Bob Hairgrove
Guest
Posts: n/a
 
      10-03-2005
On Mon, 3 Oct 2005 12:16:09 +0000 (UTC), Alfonso Morra
<(E-Mail Removed)> wrote:

>Hi,
>
>I am at the end of my tether now - after spending several days trying to
>figure how to do this. I have finally written a simple "proof of
>concept" program to test serializing a structure containing pointers
>into a "flattened" bit stream.
>
>Here is my code (it dosen't work - compiles fine, pack appears to work,
>but unpack retrieves jibberish and causes program to crash).
>
>I would be grateful for any feedback that helps fix this. My intention
>is to build on this example, and use the ideas here, to be able to
>persist any data structure (I'll write different pack/unpack routines
>for different data stuctures, just to keep things simple). Anyway,
>here's the code:
>
>
>#include "stdlib.h"
>#include "stdio.h"
>#include "string.h"


First of all, you have posted this to comp.lang.c++, so you should get
used to doing things the C++ way:

#include <cstdlib>
#include <cstdio>
#include <string>

>typedef struct {
> int l ;
> double d ;
> char* s; /* Null terminated string */
>} MyStruct ;


struct MyStruct {
int l ; // terrible names of variables here...
double d ;
const char* s; /* Null terminated string */
};

I think I'll post this "as is" and try to do a rewrite in C++. Once
you see the difference, I think you won't go back to using malloc and
free ever again.

--
Bob Hairgrove
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      10-03-2005
Bob Hairgrove wrote:
> First of all, you have posted this to comp.lang.c++, so you should get
> used to doing things the C++ way:

[snip]

The program is very much C-style, not C++. The latter would ordinarily
much prefer std::string to a char*. Check out these FAQs for more on
C++-style serialization:

http://www.parashift.com/c++-faq-lit...alization.html

Cheers! --M

 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      10-03-2005
Bob Hairgrove wrote:

> On Mon, 3 Oct 2005 12:16:09 +0000 (UTC), Alfonso Morra
> <(E-Mail Removed)> wrote:
>
> > Hi,
> >
> > I am at the end of my tether now - after spending several days
> > trying to figure how to do this. I have finally written a simple
> > "proof of concept" program to test serializing a structure
> > containing pointers into a "flattened" bit stream.


> First of all, you have posted this to comp.lang.c++, so you should get
> used to doing things the C++ way:



He's also been posting it to comp.lang.c. He's trying to come up with
some sort of hybrid solution that works in either language. Others have
pointed out the foolishness of that.




Brian
 
Reply With Quote
 
Alfonso Morra
Guest
Posts: n/a
 
      10-03-2005


Default User wrote:

> Bob Hairgrove wrote:
>
>
>>On Mon, 3 Oct 2005 12:16:09 +0000 (UTC), Alfonso Morra
>><(E-Mail Removed)> wrote:
>>
>>
>>>Hi,
>>>
>>>I am at the end of my tether now - after spending several days
>>>trying to figure how to do this. I have finally written a simple
>>>"proof of concept" program to test serializing a structure
>>>containing pointers into a "flattened" bit stream.

>
>
>>First of all, you have posted this to comp.lang.c++, so you should get
>>used to doing things the C++ way:

>
>
>
> He's also been posting it to comp.lang.c. He's trying to come up with
> some sort of hybrid solution that works in either language. Others have
> pointed out the foolishness of that.
>
>
>
>
> Brian


You sir, are an idiot.

 
Reply With Quote
 
Default User
Guest
Posts: n/a
 
      10-03-2005
Alfonso Morra wrote:



> You sir, are an idiot.



And you are plonked.




Brian
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to move from java object serialization to xml serialization? Dimitri Ognibene Java 4 09-02-2006 07:32 AM
Object serialization XML vs java serialization plasticfloor@gmail.com Java 3 06-14-2006 03:45 AM
What's wrong with this code ? (struct serialization to raw byte stream) Alfonso Morra C Programming 3 10-05-2005 04:43 AM
What's wrong with this code ? (struct serialization to raw byte str Alfonso Morra C Programming 11 10-03-2005 04:05 PM
Serialization Problems and books on serialization? sinleeh@hotmail.com Java 8 01-02-2005 02:40 PM



Advertisments