free variable when use malloc in c

Viewed 89
char **loadValues()
{
    char **toReturn;
    int i;
    toReturn = malloc(5 * sizeof(char *));
    for (i = 0; i < 5; i++)
    {
        toReturn[i] = malloc(25);              //Change the size as per your need
        strncpy(toReturn[i], "string", i + 1); //Something to copy
    }
    return toReturn;
}

I copied above part of the code. In it, the "toReturn" variable is initialized by using malloc. Don't we have to "free" this "toReturn" variable?

Don't we have to free these variables when we return them in C. I still couldn't find a clear answer and I can't find a way to free it when I return it. Can someone explain it to me?

3 Answers

You cannot free the allocated memory inside the function and return that data so that it can be used outside the function. But you still can free() the memory outside the function.

I assume that your question is: how does the function that calls loadValues and receives the pointer it returns, can free the loaded values.

If we leave loadValues as it is now, the best solution is to create another function, called freeValues and call it when we are done with the values:

void freeValues(char **values)
{
    for (i = 0; i < 5; i++)
    {
        free(values[i]);
    }
    free(values);
}

Then you can do something like this in your main program:

char **values = loadValues();
// ... use values for something
freeValues(values);

Another option, is to allocate toReturn using a single call to malloc, in which case it can be freed simply by calling to free.

Don't we have to "free" this "toReturn" variable?

Yes, eventually you'd want to free the memory after you're done with it.

I still couldn't find clear answer and I can't find a way to free it when I return it. Can someone explain it to me?

When you use the function you assign it to a new pointer, you can use this pointer, not only to access the memory block you returned, but also to free it, example:

int main()
{
    char** values = loadValues();
    
    // do something with values

    // don't need them anymore
    for (int i = 0; i < 5; i++){
        free(values[i]);
    }
    free(values);
}

Note that strncpy(toReturn[i], "string", i + 1); is likely not what you want, in each iteration you are copying only from 1 to 5 characters respectively, not the entire string, and more importantly, not the null terminator.

The third argument of strncpy should be the length of "string" plus 1 more byte for the null terminator, so 7 in this case. Alternatively, if want to copy only part of ther string, you have to null-terminate it yourself.

If the goal is to copy the entire string, you can let the compiler do that for you:

//...
toReturn = malloc(5 * sizeof(char *));
for (i = 0; i < 5; i++)
{
    toReturn[i] = strdup("string");  // duplicate string and store it in toReturn[i]
}
//...

Of course you still need to free it yourself like in the first situation.

Related