Search code examples
cmemoryrealloc

Realloc Memory Intercept


I want to read several files and add lines of text to the content. I would like to save the new changed content in a buffer. The files can be from 0 bytes to 16 MB in size. By adding the lines of text, the file can also be much larger, depending on the content.

At the beginning, I reserve 512 bytes of memory with calloc.

wchar_t *buffer = (wchar_t*)calloc(512, sizeof(wchar_t));

Whenever adding text to memory, I check if the size of the reserved memory is still sufficient with the function realloc. This works quite reliably for small files only with larger files the program crashes. Debbug is unfortunately not possible because of the constellation.

Now my question. If I extend the memory repeatedly with realloc but it fails, is the if statement with buffer == NULL correct? The buffer can theoretically not be zero, since it was already filled before.

How can I catch the error cleanly or fix it?

size_t memoryallocated = 512;

wchar_t *buffer = (wchar_t*)calloc(memoryallocated , sizeof(wchar_t));          
while (memoryuse + contenlength >= memoryallocated)
{
 memoryallocated *= 2;
 buffer = (wchar_t *)realloc(buffer, memoryallocated* sizeof(wchar_t));     
 if ((buffer == NULL))
 {
   return NULL;
 }
}

wmemcpy(buffer + memoryuse, contentbuf,contenlength);
memoryuse += contenlength;    // thx @pm100

return buffer;

Solution

  • If you read the documentation for realloc, you can see that function returns NULL if it cannot resize your buffer (due to lack of memory or any other reason). It does not return the old pointer.

    So comparing the returned value with NULL is absolutely correct.

    Aside from that you should never do

    buffer = realloc(buffer, ...);
    

    Because if realloc returns NULL you have lost the old pointer which was not freed (realloc does not free if it cannot reallocate). This will result in a memory leak.

    You should always do -

    void * new_ptr = realloc(buffer, new_size); // new_size > 0 
    
    if (new_ptr == NULL) {
        // Handle error and keep using buffer
    } else {
        buffer = new_ptr;
    }