简体   繁体   中英

How to properly allocate struct* that has char* field

I am allocating pointer to head structure using malloc, but I would like to have 'title' field have size of 100 char elements. How to properly do it?

struct tail{
    int x;
};

struct head{
    char *title;
    struct tail *next;
};

void function(){
    struct head *h;
    //this (program won't know how much to allocate for 'title':
    h = (struct head*)malloc(sizeof(struct head));

    //VS this (Segmentation fault (core dumped)):
    h->title = (char*)malloc(sizeof(char)*255);
    h->next = (struct tail*)malloc(sizeof(struct tail*));

    /*
    or maybe I should alloc h, then realloc title?
    If that's the answer, how will I free whole structure later?
    */
}

ps. I am not using char title[100] on purpose.

edit note. (char) was a typo, I have (char*) in my code

Are you compiling with -wall?

If you look at this warning you should get

so.c:16:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

The return value of malloc is a void pointer, which points to the piece of memory you are allocating - you are casting the address of the memory to a char , which is because you have missing out the pointer declaration * and thereby truncating the actual address, which then results in your segfault.

C does know how much memory to allocate for the struct from the start, as pointers have a fixed size, which is all that is being allocated when you do a malloc on your head/tail structure.

Why not use the first way, and then allocate space for title ?

h = malloc(sizeof(struct head));
h -> title = malloc(sizeof(char) * 100);
h -> next = malloc(sizeof(struct tail*));

The trick was to remember that title is a char * so all you need in h is space for a pointer, not the actual array.

You can free this simply by using:

free(h -> title);
free(h -> next);
free(h);

The problem with your second method is that h wasn't allocated, so it segfaulted. Also, you were casting the result of malloc (a void * ) to a char , which doesn't really make sense - I think you meant to cast to a char * , which isn't needed anyway, because C can convert from void * automatically.

you could do someting like create a function that creates a struct head with a given title size. Remember that you must (should) also create a free_head function that is able to destroy an object created by the create_head fucntion below.

struct head* create_head( unsigned title_size) {
     struct tail* t = malloc (sizof(struct tail) );
     if ( ! tail ){
         return NULL;
     }
     char* title = malloc ( title_size * sizeof(char) );
     if ( !title ){
          free(t)
          return NULL;
     }
     struct head* h = malloc (sizeof (struct head) );
     if ( !head ){
         free (t);
         free (title);
         return NULL;
     }
     head->title = title;
     head->next = t;
     return head;
}

Now you could simply use use the function like:

struct head* = create_head(100);

And then of course you need to write a some code the destroys the struct head properly otherwise you create a memory leak. Also rember that this function does not allocate one extra char for a terminating '\\0' byte. to terminate a C string

succes!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM