tomashauser
tomashauser

Reputation: 571

How to free reallocated and callocated memory?

How to free the memory which has been once callocated in the beggining, then reallocated and callocated right after? This ptr was my attempt but valgrind says that there has been 6 allocs and 6 frees, yet there are 90 bytes in 3 blocks definitely lost.

char *textInFile = (char *) calloc(currentLength + 1, sizeof(char) * currentLength);
char *currentLine = (char *) calloc(currentLength + 1, sizeof(char) * currentLineLength);
...
while ((textInFile[index] = getc(f)) != EOF) {
    if (index > currentLength - 3) {
        currentLength += 10;
        ptr = textInFile;
        textInFile = (char *) realloc(textInFile, currentLength);
        textInFile = (char *) calloc(currentLength, sizeof(char) * currentLength);
        free(ptr);
    }
    ...
    if (textInFile[index] == '\n') {
        int k = 0;
        for (int i = previousIndex; i < index; i++) {
            if (k > currentLineLength - 3) {
                currentLineLength += 10;
                ptr = currentLine;  
                currentLine = (char *) realloc(currentLine, currentLineLength);
                currentLine = (char *) calloc(currentLineLength, sizeof(char) * currentLineLength);
                free(ptr);
            }
    ...
    index++;
}
...
free(textInFile);
free(currentLine);

==4426== HEAP SUMMARY:

==4426== in use at exit: 90 bytes in 3 blocks

==4426== total heap usage: 9 allocs, 9 frees, 14,668 bytes allocated

==4426==

==4426== LEAK SUMMARY:

==4426== definitely lost: 90 bytes in 3 blocks

==4426== indirectly lost: 0 bytes in 0 blocks

==4426== possibly lost: 0 bytes in 0 blocks

==4426== still reachable: 0 bytes in 0 blocks

==4426== suppressed: 0 bytes in 0 blocks

Upvotes: 0

Views: 128

Answers (4)

John Bode
John Bode

Reputation: 123508

This code doesn't make any sense:

textInFile = (char *) realloc(textInFile, currentLength);
textInFile = (char *) calloc(currentLength, sizeof(char) * currentLength);

Why are you calling calloc after the realloc? What do you think that code is doing? If you're trying to zero out the extended memory, that won't work.

If you want to extend (realloc) a buffer, here's the general procedure for doing so. Assuming you allocated the buffer as

T *buffer = calloc( number_of_items, sizeof *buffer ); // sizeof *buffer == sizeof (T)

for some type T, you'd extend the buffer as follows:

T *tmp = realloc( buffer, (number_of_items + number_of_new_items) * sizeof *buffer );
if ( tmp )
{
  buffer = tmp;
  number_of_items += number_of_new_items;
}
else
{
  // reallocation was not successful, handle as appropriate
}

As a rule, you do not want to assign the result of realloc to the original pointer. If realloc fails, it will return NULL while leaving the current buffer in place, and you will overwrite your original pointer value (leading to a memory leak). You also don't want to update your size until you know the operation was successful. It's best to assign the result to a temporary pointer, then after you're sure it was successful, assign the temporary to your original pointer.

You don't need to call calloc after calling realloc. You only need to call calloc once, when you initially allocate the buffer. You can also use realloc for the initial allocation, you just pass NULL as the first parameter:

T *buffer = realloc( NULL, number_of_items * sizeof *buffer );

Edit

Applying this to your code:

while ((textInFile[index] = getc(f)) != EOF) {
  if (index > currentLength - 3) {
    ptr = realloc(textInFile, currentLength + 10);
    if ( ptr )
    {
      currentLength += 10;
      textInFile = ptr; 
    }
    else
    {
      // unable to extend textInFile
    }
    ...
        if (k > currentLineLength - 3) {
            ptr = realloc( currentLine, currentLineLength + 10 );
            if ( ptr )
            {
              currentLineLength += 10;
              currentLine = ptr;  
            }
            else
            {
              // unable to extend currentLine
            }
        }

When you're done, you'd free as

free( currentLine );
free( textInFile );

You don't need to free ptr at any point in this - you're only using it to store a temporary value.

Upvotes: 0

tomashauser
tomashauser

Reputation: 571

The answer:

ptr should have pointed to realloc which should have been freed. In the question, the original adress of textInFile was lost since it was overwritten.

ptr = (char *) realloc(currentLine, currentLineLength);
currentLine = (char *) calloc(currentLineLength, sizeof(char) * currentLineLength);
free(ptr);

Upvotes: 0

Jeremy Friesner
Jeremy Friesner

Reputation: 73121

You need to call free() on every non-NULL pointer that was returned by calloc(). If you call realloc(), then you shouldn't call free() on the pointer that you passed in as an argument to realloc(), but you should call free() on the pointer that realloc() returned. (Note: using realloc() correctly is tricky, especially if you want to handle errors correctly -- I recommend avoiding it unless it's strictly necessary)

One problem in particular with your code is this:

textInFile = (char *) realloc(textInFile, currentLength);
textInFile = (char *) calloc(currentLength, sizeof(char) * currentLength);

In the second line you overwrite textInFile's pointer with the pointer returned by calloc(), thus losing any access to the old value that was returned by realloc(), so you have no way to free that buffer; hence you have a memory leak.

Upvotes: 2

Peter Lee
Peter Lee

Reputation: 136

I think.. that you are misunderstanding realloc.

realloc is not free.

It returns alloacted memory..

your code

        textInFile = (char *) realloc(textInFile, currentLength);
        textInFile = (char *) calloc(currentLength, sizeof(char) * currentLength);
        free(ptr);

textInFile was alloacted twice.. 1st pointer is leaked..

Upvotes: 0

Related Questions