TheOptimum
TheOptimum

Reputation: 11

Struct Array Dynamic Memory Allocation in C

I'm trying to create an array of structs using dynamic memory allocation. My struct is something along the lines of:

typedef struct {
    char data1[200];
    char data2[200];
    char data3[200];
    int data4;
    double data5;
    double data6;
} randomInfo_t;

I don't know how many of these structs I need to create, which is why I'm using malloc() to dynamically create the array.

There are multiple lines of data stored within a file, similar to a CSV.

Right now, my attempt at creating the array has lead to a segmentation fault, which I suspect is due to the way I'm using malloc():

randomInfo_t *stuffArray;
int indexCounter=0;

while(fgets(buffer, 1024, fp)) {

    /* some random code here */

    stuffArray[indexCounter] = *(randomInfo_t *)malloc(sizeof(randomInfo_t *));
    assert(stuffArray[indexCounter] != NULL);

    char *readLine = strtok(buffer, " ");

    while(readLine) {
            strcpy(randomArray[indexCounter].data1, readLine);
            
                   etc...
    }

    indexCounter++;

}

I've tried debugging it myself, but I have absolutely no clue what I was doing.

Any help is appreciated. Thanks

(PS. I know that using a linked list would be a lot easier, and I would prefer to use one as well, but requirements of the code means no linked lists).

Upvotes: 0

Views: 271

Answers (2)

Marko Borković
Marko Borković

Reputation: 1922

The problem is that stuffArray is an uninitalized pointer. What you need to do is initalize it and keep track of its current size, like this:

// allocate space for 10 pointers to struct
randomInfo_t **stuffArray = malloc(sizeof(randomInfo_t*) * 10); 
int stuffArray_size = 10;
int stuffArray_used = 0;

Then when you are allocating space for another struct pointer you do it like this:

// if there are more structs than what stuffArray can currently fit realloc
if(indexCounter >= stuffArray_size) {
    stuffArray_size += 10;
    stuffArray = realloc(stuffArray, stuffArray_size * sizeof(randomInfo_t*));
}
stuffArray_used++;
// now we can allocate space for a new struct and point stuffArray[indexCounter] to the newly allocated space
stuffArray[indexCounter] = malloc(sizeof(randomInfo_t));

And now when you want to access struct member you have to use ->. So this line:

strcpy(randomArray[indexCounter].data1, readLine);

Now has to be:

strcpy(randomArray[indexCounter]->data1, readLine);

Also when you are done using the array you have to free it. Like this:

// this is where the stuffArray_used comes into play, we don't want to try freeing unallocated memory
for(int i = 0; i < stuffArray_used; i++){
    free(stuffArray[i]);
}
free(stuffArray);

Upvotes: 1

Ian Abbott
Ian Abbott

Reputation: 17513

It is not clear if you are attempting to dynamically allocate an array of randomInfo_t or an array of randomInfo_t * with each element pointing to a randomInfo_t.

Assuming you are dynamically allocating an array of randomInfo_t you can use realloc to gradually increase the size of the array:

randomInfo_t *stuffArray=NULL;
int indexCounter=0;

while(fgets(buffer, 1024, fp)) {

    /* some random code here */

    randomInfo_t *oldStuffArray = stuffArray; /* In case realloc fails */
    stuffArray = realloc(stuffArray, sizeof(*stuffArray) * (indexCounter + 1));
    if (stuffArray == NULL) {
        /*
         * realloc failed. Take appropriate action here.
         * Note that the memory pointed to by oldStuffArray is still valid.
         */
#if FOO
        /* for example: */
        fprintf(stderr, "Memory allocation failed\n");
        free(oldStuffArray);
        exit(1);
#else
        /* or you could use oldStuffArray contents and not read any more: */
        fprintf(stderr, "Memory allocation failed\n");
        stuffArray = oldStuffArray;
        break;
#endif
    }

    /* Do stuff with stuffArray[indexCounter] */

    indexCounter++;
}

Upvotes: 1

Related Questions