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

A

Alfonso Morra

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" ); /*did I need to strdup? */

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,
(strlen(m->s)+1)*sizeof(char)) ;

*size = len ;
return buff ;
}


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

/* get int*/
memcpy(&l, block, sizeof(int)) ;
/* get double*/
memcpy(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
/* get string length*/
memcpy(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
sizeof(size_t)) ;
/* get string*/
s = (char*)malloc(len+1) ;
memcpy(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 ;
}
 
D

Dik T. Winter

> 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));

Hrm, the second sizeof(int) is wrong.
> /*copy string*/
> memmove(buff + sizeof(int) + sizeof(double), m->s,
> (strlen(m->s)+1)*sizeof(char)) ;

And here you need a sizeof(size_t);
 
B

Barry Schwarz

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;

Don't cast the return from malloc. It only allows the compiler to
ignore certain errors which can lead to undefined behavior
unsigned char *memblock = NULL ;
size_t size ;

in->l = 1000 ;
in->d = 3.142857;
in->s = strdup("Simple Text" ); /*did I need to strdup? */

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

pack returns a void*. You don't need the cast to assign it to
memblock.
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) ;

sizeof(char) is always 1.
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,
(strlen(m->s)+1)*sizeof(char)) ;

*size = len ;
return buff ;
}


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

/* get int*/
memcpy(&l, block, sizeof(int)) ;
/* get double*/
memcpy(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
/* get string length*/
memcpy(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
sizeof(size_t)) ;

len is an int. But you are copying sizeof(size_t) bytes. size_t need
not have the same size as an int. Even if it does, size_t is unsigned
so the bit pattern may not be interpreted correctly when treated as an
int.
/* get string*/
s = (char*)malloc(len+1) ;
memcpy(s,(unsigned char*)block + sizeof(int) + sizeof(double)+
sizeof(size_t),len) ;

What happened to the +1? The "string" in s is not a string because it
is not '/0' terminated.
p = (MyStruct*)malloc(sizeof(*p)) ;

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

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


<<Remove the del for email>>
 
G

grocery_stocker

Alfonso said:

Hey dude -)
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.

I spent several days alone with myself in the bathroom.
Here is my code (it dosen't work - compiles fine, pack appears to work,
but unpack retrieves jibberish and causes program to crash).

And here will my be 2 cent reply.
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"

Don't we mean

#include <stdlib.h>
#include <stdio.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" ); /*did I need to strdup? */

The voices in my head are telling my strdup() isn't part of the
standard. Like also, strdup() returns a pointer to char. I think I
worded this right. About this point and time, I think you got something
more funky going on that what a bored 14 yr old has going on with the
pimped out AOL account.
memblock = (unsigned char*)pack(&size, in) ;
out = unpack(memblock) ;

Is memblock part of the holy standard? I just tried typing $man
memblock and all I got was a blank response.
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) ;

}

Okay, this is getting too technical.
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,
(strlen(m->s)+1)*sizeof(char)) ;

*size = len ;
return buff ;
}


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

/* get int*/
memcpy(&l, block, sizeof(int)) ;
/* get double*/
memcpy(&d, (unsigned char*)block + sizeof(int), sizeof(double)) ;
/* get string length*/
memcpy(&len, (unsigned char*)block + sizeof(int) + sizeof(double),
sizeof(size_t)) ;
/* get string*/
s = (char*)malloc(len+1) ;
memcpy(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 ;
}


In the end, I couldn't compile this because my OS (FreeBSD 4.8) refused
to recongnize the code. I forgot where this was going.
 

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

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top