Search code examples
carraysrealloc

Realloc a string array


I'm trying to write a function realloc 3 arrays which are created in main using malloc, but every time I try to run the program, I get an error and program stops working.

In my attempts to debug, I tried to print the arrays after "realloc" and it looks like the realloc was done successfully but after I scan into those new records, when I to to print, I get the error.

CORRECTION 1: Corrected the mistake in scanf line as suggested. Program runs into error as soon as the first new record is input

Any inputs are appreciated!

void addRecord(char** firstName,char** lastName, float* score, int * recordSize)
{
     int add,i;
     printf("How many records do you want to add? ");
     scanf("%d", &add);

     firstName = realloc(firstName, (*recordSize+add)*sizeof(char*));
     for (i=*recordSize; i<(*recordSize)+add; i++)
         firstName[i]= malloc(STRSIZE*sizeof(char));

     lastName = realloc(lastName, (*recordSize+add)*sizeof(char*));
     for (i=*recordSize; i<(*recordSize)+add; i++)
         lastName[i]= malloc(STRSIZE*sizeof(char));

     score = realloc(score, (*recordSize+add)*sizeof(float));
     printf("Please enter the record to be added: \n");
     printf("FirstName LastName Score\n");

    for (i=*recordSize; i<*recordSize+add; i++)
        scanf("%s %s %f", firstName[i], lastName[i], &score[i]);
    *recordSize +=add;
 }

Solution

  • You should be aware that your reallocations won't be visible in your main function if the pointer address changes. You're reallocating the entire array of strings, but this change only happens in your addRecord() function. When you get back to your main function, you might have a dangling pointer because realloc() can return a new memory address and free the original memory block. That is printf("%p\n", firstName); can print different things in addRecord() and your main function after addRecord() returns.

    For example:

    #include <stdio.h>
    
    /* Simulate the reallocation of bar by swapping oldbar and bar. */
    void foo(int *bar)
    {
        static int *oldbar = NULL;
    
        if (oldbar == NULL) {
            oldbar = bar;
            bar = NULL;
        } else {
            bar = oldbar;
            oldbar = NULL;
        }
    
        printf("bar after reallocating is: %p\n", (void *)bar);
    }
    
    /* Notice the extra * below and the dereferencing of the pointer, allowing
       main() to see the change. */
    void foo_works(int **bar)
    {
        static int *oldbar = NULL;
    
        if (oldbar == NULL) {
            oldbar = *bar;
            *bar = NULL;
        } else {
            *bar = oldbar;
            oldbar = NULL;
        }
    
        printf("bar after reallocating is: %p\n", (void *)bar);
    }
    
    int main(void)
    {
        int bar[] = {1, 1, 2, 3, 5, 8};
        int *barptr = bar;
    
        printf("barptr before reallocating is: %p\n", (void *)barptr);
        foo(barptr);
        printf("barptr after reallocating is: %p\n\n", (void *)barptr);
    
        printf("barptr before reallocating is: %p\n", (void *)barptr);
        foo_works(&barptr);
        printf("barptr after reallocating is: %p\n", (void *)barptr);
    }
    

    For an array of strings, you just need to add another * to the parameter and dereference as I did in the definition of foo_works(). This way you have a pointer to the array, which allows the change to be visible to your main function. Of course, this means you'll be a Three Star Programmer, and you might consider refactoring to use structures for your records instead...