Search code examples
cdynamic-arraysrealloc

realloc of array inside a struct


I'm trying to write a function that uses realloc() to extend the array as pointed to within in instance of a struct, however I can't seem to get it to work.

The relevant part of my code is:

struct data_t {
  int data_size;
  uint16_t *data;
};

void extend_data(data_t container, uint16_t value) {
    // adds an additional uint16_t to the array of DATA, updates its internal
    // variables, and initialises the new uint to VALUE.

    int len_data = sizeof(*(container->data)) / sizeof(uint16_t);
    printf("LENGTH OF DATA: %d\n", len_data);

    container->data = realloc(container->data, sizeof(*(container->data))+sizeof(uint16_t));
    container->data_size++;
    container->data[container->data_size-1] = value;

    len_data = sizeof(*(container->data)) / sizeof(uint16_t);
    printf("LENGTH OF DATA: %d\n", len_data);
    printf("data_size: %d\n", container->data_size);

    return;
}

Can anybody see what the problem is with this?


Solution

  • Edit

    As R. Sahu points out, container is not a pointer in this function - when you said the code "wasn't working", I assumed you meant that you weren't growing your array, but what you've written here won't even compile.

    Are you sure you've copied this code correctly? If so, does "not working" mean you're getting a compile-time error, a run-time error, or just unexpected output?

    If you've copied the code as written, then the first thing you need to do is change the function prototype to

    void extend_data(data_t *container, uint16_t value) {
    

    and make sure you're passing a pointer to your data_t type, otherwise the update won't be reflected in calling code.

    Original

    In the line

    container->data = realloc(container->data, sizeof(*(container->data))+sizeof(uint16_t));
    

    sizeof(*(container->data)) evaluates to sizeof (uint16_t). container->data is a pointer to, not an array of, uint16_t; sizeof will give you the size of the pointer object, not the number of elements you've allocated. What you want to do is something like the following:

    /**
     * Don't assign the result of a realloc call back to the original
     * pointer - if the call fails, realloc will return NULL and you'll
     * lose the reference to your original buffer.  Assign the result to
     * a temporary, then after making sure the temporary is not NULL,
     * assign that back to your original pointer.
     */
    uint16_t *tmp = realloc(container-data, sizeof *container->data * (container->data_size + 1) );
    if ( tmp ) 
    {
      /**
       * Only add to container->data and update the value of container->data_size
       * if the realloc call succeeded.
       */
      container->data = tmp;
      container->data[container->data_size++] = value;
    }