C Coding Style – Functions Returning Strings, Good Practice?

ccoding-stylemallocstrings

In my C programs I often need a way to make a string representation of my ADTs. Even if I don't need to print the string to screen in any way, it is neat to have such method for debugging. So this kind of function often comes up.

char * mytype_to_string( const mytype_t *t );

I actually realize that I have (at least) three options here for handling the memory for the string to return.

Alternative 1: Storing the return string in a static char array in the function. I don't need much thinking, except that the string is overwritten at every call. Which may be a problem in some occasions.

Alternative 2: Allocate the string on the heap with malloc inside the function. Really neat since I then won't need to think of the size of a buffer or the overwriting. However, I do have to remember to free() the string when done, and then I also need to assign to a temporary variable such that I can free. and then heap allocation is really much slower than stack allocation, therefore be a bottleneck if this is repeated in a loop.

Alternative 3: Pass in pointer to a buffer, and let the caller allocate that buffer. Like:

char * mytype_to_string( const mytype_t *mt, char *buf, size_t buflen ); 

This brings more effort to the caller. I also notice that this alternative gives me an other option on the order of the arguments. Which argument should I have first and last? (actually six possibilities)

So, which should I prefer? Any why? Is there some kind of unwritten standard among C developers?

Best Answer

The methods I've seen most are 2 and 3.

The user supplied buffer is actually quite simple to use:

char[128] buffer;
mytype_to_string(mt, buffer, 128);

Though most implementations will return the amount of buffer used.

Option 2 will be slower and is dangerous when using dynamically linked libraries where they may use different runtimes (and different heaps). So you can't free what has been malloced in another library. This then requires a free_string(char*) function to deal with it.