4

I am trying to dynamically reallocate memory for an array of structs (actually an array each of 2 structs but 1 included here for simplicity) that is being read from/to a file or inputted by the user.

typedef Struct
{
    char surname[21];
    char firstname[21];
    char username[21];
...
} User;

...in main():

int size = 0; /* stores no. of structs */
User* user_array = (User *) calloc(1, sizeof(User));
if(user_array == NULL)
{
    printf("Cannot allocate initial memory for data\n");
    exit(1);
}
else
    size++;

I am then trying to use a function call to increase the array when needed:

int growArray(User user_array*, int size)
{
    User *temp;
    size++;
    temp = (User *) realloc(user_array, (size * sizeof(User));
    if(temp == NULL)
    {
        printf("Cannot allocate more memory.\n");
        exit(1);
    }
    else
        user_array = temp;
    return size;
}

Unfortunately the realloc never works. Both structs are only about 200 bytes per instance and setting the initial size to say 10 will work fine, so there must be something wrong with the way I am trying to use realloc.

System is Win 7 64, on Core i5 with 4GB, running Quincy (a MinGW GUI).

7
  • 1
    int growArray(User user_array, int size)? Are you missing a *? Commented May 29, 2011 at 19:41
  • post the real code - this won't compile Commented May 29, 2011 at 19:41
  • @KennyTM I think he's missing two of them. Commented May 29, 2011 at 19:47
  • If you get this to work you can simplify the code by also doing the initial allocation with growArray. Also, be aware that your initial calloc() will initialize the first entry, while the subsequent realloc() will leave the extended area uninitialized. Like cnicutar notes, the "size++" will not be visible to the caller. Commented May 29, 2011 at 19:49
  • dantje - at the moment I am using size for my return value - sorry for leaving that out Commented May 29, 2011 at 19:55

2 Answers 2

8

realloc changes the size of the memory pointed to by user_array to the specified size, it doesn't increase it by size. Seeing as your function is called growArray, i'd presume you want it to increase the size of the array by size, in which case you need to:

int growArray(User **user_array, int currentSize, int numNewElems)
{
    const int totalSize = currentSize + numNewElems;
    User *temp = (User*)realloc(*user_array, (totalSize * sizeof(User)));

    if (temp == NULL)
    {
        printf("Cannot allocate more memory.\n");
        return 0;
    }
    else
    {
        *user_array = temp;
    }

    return totalSize;
}

Note that growArray takes the address of user_array, the reason for this is that realloc might move the memory if it couldn't extend the existing block to the required size.

To use it:

int size = 0;
User* user_array = (User *) calloc(1, sizeof(User));
if(user_array == NULL)
{
    printf("Cannot allocate initial memory for data\n");
    exit(1);
}

/* add 10 new elements to the array */
size = growArray(&user_array, size, 10);
Sign up to request clarification or add additional context in comments.

2 Comments

Size is equal to the number of structs in the array (before it is increased) when it is passed to growArray. The size++ in growArray will increase this to the new number (intended to be increased by 1 at a time - from an unknown no. of entries in the file or by user adding) so I believe size * sizeof(User) is correct for this approach. I notice you have used double indirection operator as @cnicutar has, I'm still trying to get my head around what is happening there. This must be where I am going wrong... if I don't do it this way, I will still be using the old start address of user_array?
Yeah, that could be your problem. realloc might not be able to extend your existing user_array pointers memory block to be big enough for the new size. If this happens, it allocates a new block of memory somewhere else, and copies everything from the user_array over. The return value is the new memory location. Using the pointer-to-a-pointer allows growArray to update the value of user_array of the caller, as its previous value is now invalid.
4

You're changing the value of user_array locally. The value is lost when the function returns. Pass a pointer to the user_array pointer instead.

2 Comments

Sorry I did forget to add the * to my code above... it's fixed now.
Thanks - this was the problem. I didn't understand until other posters were more specific about how to do this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.