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?
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()
;)