Q:

Seg fault issue in mergesort algorithm with dynamic array

I'm trying to implement the mergesort algorithm using a dynamic array structure in c, but when i call the function to split the  original array instead of getting two subarrays i get a seg fault error.
I'm pretty sure it has something to deal with how i define the size of my structure, but i cannot get over it. Here's how i've defined my structure and how i create and initialize it:
typedef struct dynarray
{
   void **memory;
   size_t allocated; //total size of the array
   size_t used;  //used size of the array
   int index;
} dynarray;

//creates a new, empty, dynarray
void create_dynarray(dynarray **array, size_t size)
{
  *array = calloc(size, sizeof(array));
  (*array)->memory = NULL;
  (*array)->allocated = 0;
  (*array)->used = 0;
  (*array)->index = -1;
}

This how i've defined my mergesort functions

//function used to slice the dynarray in two subarrays and call merge function
void* dynarray_mergesort(dynarray *param){
  if(dynarray_length(param)>1){    
   param->index = 0;
   printf("index of first:%d\t", param->index);
   size_t size = param->used;   
   size_t m = size/2;
   size_t n = size - size/2;
   struct dynarray *l; 
   create_dynarray(&l, m);
   printf("index of left:%d\t", l->index);
   struct dynarray *r;
   create_dynarray(&r, n);  
   printf("index of right:%d\n", r->index);

     for(int i = 0 ; i < m; i++){
       add_elem(l, param->memory[i]);

     }for(int j = m; j < n; j++){
       add_elem(r, param->memory[j]);
     }
       puts("first");
       print_array(l);

       puts("second");
       print_array(r);

       dynarray_mergesort(l);
       dynarray_mergesort(r);
       //dynarray_merge(param, l , r, size);
  }  
  return param;
}

//function used to mergesort the array

void* dynarray_merge(dynarray *param, dynarray *l, dynarray *r, int size){
     int i,j,k; 
     while(i < size/2 && j < size-size/2){
    if(l->memory[i] < r->memory[j]){
      param->memory[k] = l->memory[i];  
      i++;
      k++;
    }else{     
          param->memory[k] = r->memory[j];
      j++;
          k++;    
        }
     }
     while(i < size/2)
       param->memory[k++] = l->memory[i++];
     }while(j < size-size/2){
       param->memory[k++] = r->memory[j++];
     }
   return param;
}

//function used to mergesort the array

void* dynarray_merge(dynarray *param, dynarray *l, dynarray *r, int size){
     int i,j,k; 
     while(i < size/2 && j < size-size/2){
    if(l->memory[i] < r->memory[j]){
      param->memory[k] = l->memory[i];  
      i++;
      k++;
    }else{     
          param->memory[k] = r->memory[j];
      j++;
          k++;    
        }
     }
     while(i < size/2){
       param->memory[k++] = l->memory[i++];
     }while(j < size-size/2){
       param->memory[k++] = r->memory[j++];
     }
   return param;
}

Probably i'm confused on how the size of my dynamic array is defined and how i have to treat it in my functions. Here's a compilable example to help you understand the problem. It is pretty long but most functions can be ignored as they are utility functions and they seem to work good. The problem is located in the mergesort function, but i'm afraid it could be related on how i've defined my dynarraystructure.
Ps. the line calling the dynarray_merge(param, l , r, size); is commented because i'm working on problems located  in the  dynarray_mergesort(dynarray *param); 
Ps2: the printf functions called inside the dynarray_mergesort(dynarray *param); are used as debugging infos.
#include<stdio.h>
#include<stdlib.h>

typedef struct dynarray
{
   void **memory;
   size_t allocated;
   size_t used;
   int index;

} dynarray;

//get length of the dynarray
int dynarray_length(dynarray *array)
{
  return array->index + 1;
}

//retrieves an element in a specific position of the dynarray
void* get_i_elem(dynarray *array,int index)
{
  if (index < 0 || index > array->index) return NULL;

  return array->memory[index];
}

//print arrays, useful to test 
void print_array(dynarray *array)
{  
   for(int i = 0; i < dynarray_length(array); i++) {
     printf("%d\t", *(int *)get_i_elem(array, i));
     //puts("");
   }

}

//creates a new, empty, dynarray
void create_dynarray(dynarray **array, size_t size)
{
  *array = calloc(size, sizeof(array));
  (*array)->memory = NULL;
  (*array)->allocated = 0;
  (*array)->used = 0;
  (*array)->index = -1;
}

//adds a new element at the bottom of dynarray
void add_elem(dynarray *array, void *data)
{
  size_t toallocate;
  size_t size = sizeof(void *);
  if ((array->allocated - array->used) < size){ // if M - N ...
    toallocate = array->allocated == 0 ? size : (array->allocated * 2);
    array->memory = realloc(array->memory, toallocate);
    array->allocated = toallocate;
  }

   array->memory[++array->index] = data;
   array->used = array->used + size;
}

//function used to slice the dynarray in two subarrays and call merge function
void* dynarray_mergesort(dynarray *param){
  if(dynarray_length(param)>1){    
   param->index = 0;
   printf("index of first:%d\t", param->index);
   size_t size = param->used;   
   size_t m = size/2;
   size_t n = size - size/2;
   struct dynarray *l; 
   create_dynarray(&l, m);
   printf("index of left:%d\t", l->index);
   struct dynarray *r;
   create_dynarray(&r, n);  
   printf("index of right:%d\n", r->index);

     for(int i = 0 ; i < m; i++){
       add_elem(l, param->memory[i]);

     }for(int j = m; j < n; j++){
       add_elem(r, param->memory[j]);
     }
       puts("first");
       print_array(l);

       puts("second");
       print_array(r);

       dynarray_mergesort(l);
       dynarray_mergesort(r);
       //dynarray_merge(param, l , r, size);
  }  
  return param;
}

//function used to mergesort the array
void* dynarray_merge(dynarray *param, dynarray *l, dynarray *r, int size){
     int i,j,k; 
     while(i < size/2 && j < size-size/2){
    if(l->memory[i] < r->memory[j]){
      param->memory[k] = l->memory[i];  
      i++;
      k++;
    }else{     
          param->memory[k] = r->memory[j];
      j++;
          k++;    
        }
     }
     while(i < size/2){
       param->memory[k++] = l->memory[i++];
     }while(j < size-size/2){
       param->memory[k++] = r->memory[j++];
     }
   return param;
}

int main(){

  struct dynarray *a;
  create_dynarray(&a, 5);
  int arr[5] = {18,14, 20,16,12};
  int *ap = malloc(sizeof(int));
  int *bp = malloc(sizeof(int));
  int *cp = malloc(sizeof(int));
  int *dp = malloc(sizeof(int));
  int *ep = malloc(sizeof(int));
  *ap = arr[0];
  *bp = arr[1];
  *cp = arr[2];
  *dp = arr[3];
  *ep = arr[4];
   add_elem(a, ap);
   add_elem(a, bp);
   add_elem(a, cp);
   add_elem(a, dp);
   add_elem(a, ep);
   dynarray_mergesort(a);   
   print_array(a);

}

A:

In addition to the allocation shortfall mentioned in the comments below your question (e.g. needing *array = calloc(size, sizeof **array);), you have a simple error leading to your SegFault (you have other errors as well). You are storing the number of bytes in the size variable in dynarray_mergesort, not the number of pointers. So in dynarray_mergesort when you declare size_t size = param->used; your value of size is multiple of sizeof(void*) (e.g. sizeof(a_pointer)) times the number of pointers you have actually used. This leads to incorrect values for m and n.
To remedy the problem, you can simply do:
   size_t size = param->used / sizeof(void*);

You have another error with your loop limits in:
     for(size_t j = m; j < n; j++){
       add_elem(r, param->memory[j]);
     }

Where m = size/2; and n = size - size/2;. You actually need your limits of m -> size, e.g.:
     for(size_t j = m; j < size; j++){
       add_elem(r, param->memory[j]);
     }

(note: above the proper type for i and j are both size_t to correspond to m and n and prevent "comparison between signed and unsigned integer expressions")
As noted in my comment, you have uninitialized value problems in dynarray_merge. You need to initialize i and k, e.g.
 int i=0, j=0, k=0; 

before you attempt:
   i++;
   k++;

With those changes your code runs to the end without problems (other than leaking memory):
$ ./bin/dynarraymergeorig
index of first:0        index of left:-1        index of right:-1
first
18      14
second
20      16      12
index of first:0        index of left:-1        index of right:-1
first
18
second
14
index of first:0        index of left:-1        index of right:-1
first
20
second
16      12
index of first:0        index of left:-1        index of right:-1
first
16
second
12
18

You still have problems merging your list (that is left to you to further investigate), but your SegFault issue is solved. Let me know if you have further questions. (other than on the changes required to fix your merge algorithm left to you)

