Using calloc() to set up char array, also "freeing" array when done

Katarn picture Katarn · Jun 21, 2014 · Viewed 24.3k times · Source

I'm trying to set up an array of strings (in C, using Linux). The array will hold 11 strings (static length). I initially had the array set up as:

char Answers[10][100];

but in my code I have a portion that calls fgets(input,sizeof(input),stdin). When this fgets() portion is called, the final element of my Answers array was being overwritten with the value of input (something about Answers' location on the stack?). So now I'm trying to "lock-in" the memory I use for my Answers array. Would I use

char Answers=calloc(11*sizeof(char));

OR

Run it through a loop--

char Answers[10];
for(c=0;c<=10;c++)
{
    Answers[c]=calloc(1*sizeof(char);
}

Also, I'll need to use atexit() to free the allocated memory when I'm done... What would be the best way to do this since I can't pass arguments inside atexit()?

atexit(Free);

void Free()
{
    free(Answers);
}

Thanks in advance!

Answer

Zach P picture Zach P · Jun 21, 2014

Okay, lots of misunderstandings, I guess. Most pieces of code there are incorrect. You asked for 11 strings so char Answers[10][100]; is incorrect and you should type char Answers[11][100]; instead, that was the reason why it skipped input. About the mistakes... First - calloc() has TWO parameters and not one, like malloc(), as in the following signature:

void *calloc(size_t nmemb, size_t size);

returns a void* to the area of memory allocated, first parameter is the number of elements that you'd like to allocate and second is the size of each element. Second, as typed above, it returns a POINTER, a void one, so you can't perform this piece of code correctly:

char Answers[10];
for(c=0;c<=10;c++)
{
    Answers[c] = calloc(11*sizeof(char));
}

What's the problem ? FIRST, parameters, as said. But second is the fact you made an array of chars and not CHAR POINTERS as needed. Should be this way:

char* Answers[11]; //As you requested 11 elements
for(c=0;c<=10;c++)
{
    Answers[c] = (char*) calloc(1, MY_STR_LENGTH);
}

When MY_STR_LENGTH is a constant of 100, as shown in your example. We used casting upon the void pointer, we corrected the use of calloc and the declaration of the char pointers. Now this code is correct - also, why do you use calloc? Usually there's no need to do so in a string. By the way, no need for a function when it's one line anyway. The second way to declare this is this way:

char **Answers = calloc(11, sizeof(char*));
for(i = 0 ; i < 11 ; i++)
{
   Answers[i] = calloc(1, sizeof(char)*MY_STRING_LENGTH); //Basically it is MY_STRING_LENGTH as sizeof(char) is almost always one, but it's there only for the readability of the code.
}

This is it, hope you understand. Read more about memory allocation in C here:

About malloc() About calloc() About realloc()