Thread: Elastic array block with malloc realloc

  1. #1
    Registered User
    Join Date
    Jan 2016
    Posts
    43

    Elastic array block with malloc realloc

    I'm trying to implement a dynamic array using a struct:

    Code:
    typedef struct
    {
      size_t count, el_size, alloc_count;
      void *data;
    } List;
    Then I can start off the array using:

    Code:
    List *List_new(size_t alloc_count, size_t el_size)
    {
      List *list = malloc(sizeof *list + alloc_count * el_size);
     
      if (list == NULL)
        return NULL;
      
      list->count = 0;
      list->el_size = el_size;
      list->alloc_count = alloc_count;
      return list;
    }
    However when I want to realloc the array, I'm not seeing what I'm doing wrong with this function as it is seg-faulting when copying the next element using memcpy after the realloc has been done:

    Code:
    bool List_add(List *list, void *data)
    {
      if (list->count > list->alloc_count - 1)
        {
          List *swap = (List *) realloc(list, sizeof *list + (list->alloc_count + 256) * list->el_size);
          
          if (swap == NULL)
            return 0;
    
          list = swap;
          list->alloc_count += 256;
        }
    
      memcpy(list + sizeof *list + list->count * list->el_size, data, list->el_size);
      list->count++;
      return 1;
    }

  2. #2
    Registered User
    Join Date
    Jan 2016
    Posts
    43
    If I add elements to the block before that realloc, memcpy works fine.

  3. #3
    Registered User
    Join Date
    Jan 2016
    Posts
    43
    Well, just realized that the static size_t vars in the struct are anchoring the struct down from dynamic reallocation. The allocation occurs but then it overflows its neighbors as a result thus causing a seg fault.

    :/

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,631
    If you're still having problems, post a complete program that I can run.
    Also post the input.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Dec 2017
    Posts
    1,631
    I think this is what you are trying to do.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
     
    #define EXTEND_SIZE 256
     
    typedef struct {
        size_t count, el_size, alloc_count;
        char data[];
    } List;
     
    List *List_new(size_t alloc_count, size_t el_size) {
        List *list = malloc(sizeof *list + alloc_count * el_size);
        if (list) {
            list->count = 0;
            list->el_size = el_size;
            list->alloc_count = alloc_count;
        }
        return list;
    }
     
    bool List_add(List **list, void *data) {
        if ((*list)->count >= (*list)->alloc_count) {
          List *swap = realloc(*list, sizeof **list +
              ((*list)->alloc_count + EXTEND_SIZE) * (*list)->el_size);
          if (!swap)
            return false;
          *list = swap;
          (*list)->alloc_count += EXTEND_SIZE;
        }
     
        memcpy((*list)->data + (*list)->count * (*list)->el_size, data,
               (*list)->el_size);
     
        (*list)->count++;
        return true;
    }
     
    int main() {
        List *list = List_new(2, sizeof(int));
     
        int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        for (size_t i = 0; i < sizeof a / sizeof *a; ++i)
            if (!List_add(&list, &a[i])) {
                printf("Problem reallocating memory.\n");
                return EXIT_FAILURE;
            }
     
        for (size_t i = 0; i < list->count; ++i)
            printf("%d ", ((int*)list->data)[i]);
        putchar('\n');
     
        free(list);
     
        return 0;
    }
    Last edited by john.c; 12-04-2019 at 06:15 PM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  6. #6
    Registered User
    Join Date
    Jan 2016
    Posts
    43
    Yes that is what I was trying to do. Thanks!
    Though I also managed to work it out using two mallocs for the list and then calling realloc on list->data alone.

    Code:
    List *list = malloc(sizeof *list);
    list->data = calloc(alloc_count, el_size);
    char *swap = realloc(list->data, (list->alloc_count + EXTEND_SIZE) * list->el_size);
    This obviously works. Though I'm curious to find out which method has any benefit over the other.

    I understand the notation
    Code:
    char data[]
    in the struct is a newer C99 feature.

  7. #7
    Registered User
    Join Date
    Jan 2016
    Posts
    43
    The correct term is "Flexible array member" for the data field in the struct. Feature introduced in C99.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. malloc/realloc
    By RagingGrim in forum C Programming
    Replies: 1
    Last Post: 11-03-2014, 02:50 PM
  2. About malloc,realloc,pointer and array
    By ampc in forum C Programming
    Replies: 9
    Last Post: 11-29-2010, 02:43 AM
  3. Struct array malloc and realloc
    By pseudonoma in forum C Programming
    Replies: 3
    Last Post: 03-01-2008, 09:16 PM
  4. realloc() doesnt copy the block correctly!
    By TalosChen in forum C Programming
    Replies: 7
    Last Post: 05-19-2006, 05:33 AM
  5. Need help on malloc and realloc
    By YevGenius in forum C Programming
    Replies: 8
    Last Post: 03-06-2004, 01:55 AM

Tags for this Thread