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

Discussion in 'C Programming' started by Alfonso Morra, Oct 3, 2005.

  1. 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 ;
    }
    Alfonso Morra, Oct 3, 2005
    #1
    1. Advertising

  2. In article <dhr6uf$4b0$-infra.bt.com> Alfonso Morra <> writes:
    ....
    > 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);
    --
    dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
    home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
    Dik T. Winter, Oct 3, 2005
    #2
    1. Advertising

  3. On Mon, 3 Oct 2005 12:07:43 +0000 (UTC), 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;


    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>>
    Barry Schwarz, Oct 4, 2005
    #3
  4. Alfonso Morra wrote:
    > Hi,


    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>
    #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? */
    >


    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.
    grocery_stocker, Oct 5, 2005
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alfonso Morra
    Replies:
    11
    Views:
    449
    John Devereux
    Oct 3, 2005
  2. Deep
    Replies:
    6
    Views:
    481
    Nick Keighley
    Feb 28, 2007
  3. Alfonso Morra
    Replies:
    15
    Views:
    567
    Bob Hairgrove
    Oct 4, 2005
  4. dolphin
    Replies:
    6
    Views:
    554
    Thomas Fritsch
    Mar 18, 2007
  5. Roedy Green

    byte stream vs char stream buffer

    Roedy Green, May 7, 2014, in forum: Java
    Replies:
    20
    Views:
    196
    Silvio
    May 18, 2014
Loading...

Share This Page