Thread: Elastic array block with malloc realloc

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

    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
    34
    If I add elements to the block before that realloc, memcpy works fine.

  3. #3
    Registered User
    Join Date
    Jan 2016
    Posts
    34
    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
    694
    If you're still having problems, post a complete program that I can run.
    Also post the input.
    The world hangs on a thin thread, and that is the psyche of man. - Carl Jung

  5. #5
    Registered User
    Join Date
    Dec 2017
    Posts
    694
    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; 2 Days Ago at 06:15 PM.
    The world hangs on a thin thread, and that is the psyche of man. - Carl Jung

  6. #6
    Registered User
    Join Date
    Jan 2016
    Posts
    34
    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.

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