Neo
Neo

Reputation: 391

Unable to malloc string in struct

My struct looks like this:

struct tree{
    char *name;
    int num_subdirs;
    struct tree **subdirs;
}

I am receiving a buffer that contains this entire tree serialized in a buffer. I am trying to deserialize it in this function:

struct tree *t;
//buffer is filled, received from somewhere else.
int res = deserialize(t, buf); //call function deserialize

//deserialize function
            //buf = {../,2}{sd,0}{|}{sr,1}{sk,0}{|}{|}
   │406     int dfsDeserialize(struct tree *dt, void *buf, int *q){                                                                                                                       │
   │407         char name[MAXPATHLEN];                                                                                                                                                           │
   │408         char delim[3];                                                                                                                                                                   │
   │409         int len, numsubs, i;                                                                                                                                                             │
                                                                                                                                                        │
   │411         sscanf(buf+(*q),"%3s",delim);                                                                                                                                                    │
   │412         if(!strcmp(delim,"{|}")){                                                                                                                                                        │
   │413             (*q)+=3;                                                                                                                                                                     │
   │414             return 1;                                                                                                                                                                    │
   │415         }                                                                                                                                                                                │
   │416         sscanf((buf + (*q)), "{%[^,],%d}%n", name, &numsubs, &len);                                                                                                                      │                                                                                                                                          │
  >│419         int slen = strlen(name);                                                                                                                                                         │
   │420         dt->name = calloc(slen + 1, 1);                                                                                                                                                  │
   │421         dt->subdirs = malloc(numsubs*sizeof(struct tree *));                                                                                                                      │
   │422         strcpy(dt->name, name);                                                                                                                                                          │
   │423         dt->num_subdirs = numsubs;                                                                                                                                                       │
   │424         (*q)+=len;                                                                                                                                                                       │
   │425         for(i = 0; i< numsubs; i++){                                                                                                                                                     │
   │426             dt->subdirs[i] = malloc(sizeof(struct tree));                                                                                                                         │
   │427             dfsDeserialize(dt->subdirs[i], buf, q);                                                                                                                                      │
   │428         }                                                                                                                                                                                │
   │429         return 0;                                                                                                                                                                        │
   │430     }   

                                                                                                                                                                             │

I have tried several different ways of allocating memory for string but it fails every single time! I don't know why is t->name always 0x0. Please help.

Upvotes: 0

Views: 87

Answers (2)

M.M
M.M

Reputation: 141586

C uses "pass by value". When you pass an argument to a function, the function receives a copy of the argument. So when you have:

struct tree *t;
int res = deserialize(t, buf); //call function deserialize

nothing that the function does can affect t. The function gets a copy of the current value of t. (Since t is uninitialized, this may cause undefined behaviour).

Instead you need to tell the function where t is found in memory:

int res = deserialize(&t, buf);

and the function might look like:

int deserialize(struct tree **p_t, void *buf)
{
    struct tree *t = malloc(sizeof *t);
    // ... set up t as before

    // tell the caller about what we did
    *p_t = t;
}

An alternative approach would be to leave deserialize as it is but remove the malloc entirely; and require that the caller allocates space before calling the function. This is more flexible as then the caller can choose to use automatic allocation or dynamic allocation.

Upvotes: 0

AndersK
AndersK

Reputation: 36082

I think the culprit is this

t = malloc(sizeof(sizeof tree));

You probably meant

t = malloc(sizeof(struct tree));

you can also use the more handier strdup to copy a string on the heap

t->name = strdup(name);

Upvotes: 2

Related Questions