carraysstructfilesystemsgdbm

Convert struct in byte array and store in db. Read db and get byte array to recreate the struct in C


Hello everyone sorry for asking but I could find any appropriate solution. I am working on a file system where I save each file node as key-value pair in a GDBM database. I have a struct which has some attributes and I convert this to a byte array

struct mystruct:

typedef struct nold{
char* name;
char* surname;
 int age;
}mystruct;

I convert it as following to a byte array

dead.name="john";
dead.surname="doe";
dead.age=22;

//copy bytes of the our struct 
char buffer[sizeof(dead)]; 
memcpy(buffer, &dead, sizeof(dead));

to store in a database we use a datum structure which is as following:

 typedef struct {
         char *dptr;
         int  dsize;
      } datum

I fill the datum structure as following:

//create a key datum
char* k="file.txt";
key.dptr=k;
key.dsize=strlen(k)+1;



//create a value datum  here I assign bytes
value.dptr=buffer;
value.dsize = sizeof(dead);

Now I store in GDBM as key-value pair

Then in another file I read the data I store and try to recast it back to a struct

datum result;

//read
result=gdbm_fetch(file,key);

char* bytes=result.dptr;

mystruct* reborn;

reborn=(mystruct*)bytes;


//print from our new struct
printf("%s\n",reborn->name);
printf("%s\n",reborn->surname);
printf("%d\n",reborn->age);

It prints the following:

E���D$�$ˈ�k����E��
$�$ˈ�k����E��
22

It manages to bring back the struct but data of char* is lost. Only the integer data is covered. Any idea why that happening? How to solve it? It it cant be solved by storing a byte array what about converting the byte array to hex or base64 and store it as such.

I really am struggling with this one.Thank you in advance.


Solution

  • A pointer inside struct is just a pointer to character array not the character array itself:

    typedef struct nold{
       char* name;
       char* surname;
       int age;
    }mystruct;
    
    mystruct s;
    s.name = "Salam";
    

    This will reserver a memory space for string "Salam", put string Salam into and return back the pointer to s.name.

    now you're copying entire struct into something other, youre copying from struct address with sizeof(mystruct) which isn't hold string "Salam" actually, it just holds a pointer to "Salam".

    If you want to do this way, you have to preallocate some space for name :

    #define MAX_NAME_LEN    50
    typedef struct nold{
       char name[MAX_NAME_LEN];
       char surname[MAX_NAME_LEN];
       int age;
    }mystruct;
    
    mystruct s;
    strcpy(s.name, "Salam");
    

    now memcpy will work

    mystruct d;
    memcpy(&d, &s, sizeof(mystruct);