TL;DR: Am I correctly passing my array into grow()?
I am trying to dynamically resize an array when adding elements to it. Currently I am getting an error message:
free(): double free detected in tcache 2
I am very sure that I am somehow passing this argument incorrectly but I'm relatively knew to pointers so I could use a tip. here is my main function, I've stripped out most of it. The problem is most like with the add() and grow() methods.
Edit: I should add that if I bypass add() just try calling grow() from main it works correctly.
main:
int main(int argc, char *argv[]){
    // declaring the dynamic array 
    const int SIZE = 2;
    float * q;
    q = (float*)malloc(sizeof(float) * SIZE); // initial memory allocation 
    int tail = 0;   // tail is the index in which we will add items
    int capacity = SIZE; 
    // add stuff to the array
    add(10.0, q, &tail, &capacity);
    add(20.0, q, &tail, &capacity); // crashes during this call!
    return 0;
}
Here are my add() and grow() methods which are contained in another file.  Everything seems to be working great until I try to call grow for the second time.
add:
void add(float element, float* q, int* tail, int* capacity){
    // add the element 
    q[*tail] = element;
    // increment tail
    ++*tail;
    // do we need to resize the array?
    if(*tail >= (*capacity) / 2){
        // capacity is already an int* so we don't need the & symbol
        grow(&q, *capacity);
        // update capacity
        *capacity = (*capacity) * 2;
    }
    return;
}
grow
void grow(float* *q, const int capacity){
    printf("# start of grow... capacity = %d\n", capacity);
    // creating temp array 
    float  * tmp = (float*)malloc(sizeof(float) * (capacity * 2));
    // copying values
    int i;
    for (i = 0; i < capacity; ++i){
        tmp[i] = (*q)[i];
    }
    // de-allocate old q
    free(*q);
    // re-assign 
    *q = tmp;
}
 
    