I'm getting back into C after a long break, and as always the problems lie in use of pointers and general memory management.
My specific problem arises from the use of realloc on a struct in order to dynamically grow it as an array as required. I've never really worked with struct arrays before so I do apologise in advance.
Note: I haven't gotten as far as adding any data to the struct data fields as of yet. I have also renamed all variables to generic names for the purpose of this example.
Here's my struct definition:
typedef struct a_struct
{
    char a;
    char b;
    int num;
} TheStruct;
I allocate the first struct via calloc:
TheStruct *new_structInstance(void)
{
    TheStruct *structInstance = NULL;
    structInstance = calloc(1, sizeof(TheStruct));
    return structInstance;
}
This is my attempt at reallocating the first struct into an array of them, which is where I'm almost certainly going wrong:
void add_structInstance_to_array(TheStruct *structInstance, int *numElements, 
int *bufferLen)
{
    if (*numElements == *bufferLen) {
        *bufferLen += GROWBY; // #define 16
        TheStruct *newstructInstance = realloc(structInstance, 
*bufferLen * sizeof(structInstance));
        if (newstructInstance == NULL) {
            free(structInstance);
            printf("Error: Memory could not be allocated.");
            exit(EXIT_FAILURE);
        }
        else if(structInstance != newstructInstance) {
            structInstance = newstructInstance;
        }
        newstructInstance = NULL;
    }
    *numElements += 1;
}
I free the array of structs thus:
void free_struct_array(TheStruct *structInstance, int *numElements)
{
    for(int i = *numElements-1; i >= 0; i--) {
        free(&structInstance[i]);
    }
    free(structInstance);
}
Note that the input text file input format read by fgets in main approximately:
char char int
And I drive the whole thing in main:
void main()
{
    TheStruct *structInstance = new_structInstance();
    int initialCreated = 0;
    int bufferLen = 0, numElements = 0;
    char buffer[BUFFER]; // #define 20
    FILE *file = fopen("input.txt", "r");
    while(fgets(buffer, sizeof(buffer), file) != NULL) {
        if(!initialCreated){
            initialCreated = 1;
        }
        else {
            add_structInstance_to_array(structInstance, &numElements, &bufferLen);
        }
    }
    // Free memory
    fclose(file);
    free_struct_array(structInstance, &numElements);
}
Compiling the code generates the following terminal output:
free(): double free detected in tcache 2 Aborted (core dumped)
Valgrind outputs the following (I've skipped more verbose output as it includes my filesystem folder structure):
==102002== LEAK SUMMARY:
==102002==    definitely lost: 128 bytes in 1 blocks
==102002==    indirectly lost: 0 bytes in 0 blocks
==102002==      possibly lost: 0 bytes in 0 blocks
==102002==    still reachable: 472 bytes in 1 blocks
==102002==         suppressed: 0 bytes in 0 blocks
==102002==
==102002== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
If there is any way I can output more useful information without exposing my file structure, please let me know.
I tried an "easier" version of this example, instead having a single struct and running realloc on an array within the struct, e.g.:
typedef struct a_struct
{
   int *arr;
}
The above worked fine. Modifying the example to use structs as the array elements instead, a bit like a linked list I suppose, is my intention, so that I can access the struct array such as:
a_struct[element].datatype = something;
int getInt = a_struct[element].inttype;
So I suppose the question is, is it possible using my approach above, and if so, where am I going wrong and is there a better approach?
 
    