Reputation: 571
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
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
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
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
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