Search code examples
arrayscmemorymemory-managementmalloc

Passing an array of structs where one of the fields is another array, to a function


This is my struct.

    typedef struct {
        uint8_t *data;
        size_t size;
    } buffer;

I initialize it like this in my main function.

buffer *array;
array = calloc(255, sizeof(*array));
//check for error
for (int i = 0; i < 255; i++) {
    array[i].data = malloc(sizeof(*array->data));
    //check for error
}

Then I pass it to a function.

ArrayFunction(&array);

This is how it's defined

void ArrayFunction(buffer **array) {
    // Doing something to determine somesize
    for (int i = 0; i < 255; i++) {
        array[i]->size = 100;
        array[i]->data = calloc(100, sizeof(uint8_t));
        //check for error
        //Setting the data to something useful
    }
}

When looking at my program through a debugger, my initialization in the main function seems fine, memory is valid. Once it enters the ArrayFunction, memory past the 0th element is invalid or uninitialized which causes a segmentation fault at the point of trying to calloc. It does work for the 0th and so does the setting data step.


Solution

  • You're trying too hard. You don't need double pointers.

    Explanations in the comments starting with //**

    You probably just want this:

    #include <stdint.h>
    #include <stdlib.h>
    
    typedef struct {
      uint8_t* data;
      size_t size;
    } buffer;
    
    void ArrayFunction(buffer *arr) {  //** just pass the buffer (t's a pointer)
      const int somesize = 11;         //** just made up some value
    
      for (int i = 0; i < 255; i++) {
        arr[i].size = somesize;
        arr[i].data = calloc(somesize, sizeof(uint8_t));
            
      }
    }
    
    int main(int argc, char* argv[])
    {
      buffer* array;
      array = calloc(255, sizeof(*array));
      //check for error
      for (int i = 0; i < 255; i++) {
        array[i].data = malloc(sizeof(*array->data));
        //check for error
      }
    
      ArrayFunction(array);             //** just pass the pointer
    }