Search code examples
cmemory-leaksmallocfree

How can I write this C function so the users can call it without using "free" afterwards?


I am very new to C programming and have a basic question about memory management.

I have written the following code (which works!) to encode some ASCII characters into a certain format I need:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

const char *hexdigits = "0123456789ABCDEF";

/*
 * Each ASCII byte is encoded as two hexadecimal digits.
 */
char* makeHex (uint8_t* inputBuffer, int inputSize) {
    int i, j;
    char* compositionBuffer = (char*) malloc(inputSize*2 + 1);
    for (i = j = 0; i < inputSize; i++) {
        unsigned char c;
        c = (inputBuffer[i] >> 4) & 0xf;
        compositionBuffer[j++] = hexdigits[c];
        c = inputBuffer[i] & 0xf;
        compositionBuffer[j++] = hexdigits[c];
    }
    return compositionBuffer;
}

int main(void) {
  char a[] = "ABCD";
  uint8_t* inputBuffer = (uint8_t*) a;
  int inputSize = sizeof(inputBuffer);
  int q;
  for (q = 0; q < 10000; q++) {
    char* p = makeHex(inputBuffer, inputSize);
    puts(p); // This outputs "41424344" which is correct.
    free(p); // I am interested in this line
  }
}

Now, I'd like to be able to perform this function without having to remember to run free(p) every time. If I simply remove that line, there is a memory leak.

Please can somebody suggest an alternative way to write this, so the users of the function don't need to concern themselves with memory management?


Solution

  • While you might be able to automate the freeing of memory allocated by malloc() in certain scenarios, in practice it's entirely typical for a C function that returns a pointer to require the caller to do something to clean up. The clean-up might be a simple call to free(), as in your example, or it might be some specific function if it's a data structure that has complex clean-up requirements.

    If you define a function that returns a char *, any experienced C programmer who reads the code will be alive to the fact that the caller might have to free it. I would be careful to document any instance where that isn't the case.

    In practice, if the function returned a pointer to something that didn't need to be free'd, I'd define the return type as const. In such a situation case, it's very probable that the data returned is something the caller shouldn't manipulate, and the compiler should warn if I try to free a const pointer.

    In short, stop worrying, and learn to love free() ;)