returning string from function without malloc

There are three common ways to return a string from a function. (Well, actually there are none, but there are three common ways to return a pointer to a string, which the caller can then use to access the string.)

  1. Allocate space for the string using malloc() inside the function. This is the most flexible method, but it makes the caller responsible for free()ing the allocated array. It can also impose some performance overhead.

  2. Require the caller to allocate space for the string and pass in a pointer to that space. This imposes some inconvenience on the caller. In particular, the caller has to decide how big the string can be.

  3. Return a pointer to (the first element of) a static array defined inside the function. The array will continue to exist after the function returns, but there's only one copy, which means that successive calls will clobber the result returned by previous calls. It also means the array has to be of some fixed size, chosen when you write the code.


You can not return temporary from a function and unless you use a malloc your character array defined in the function will be a temporary. An alterantive solution is to pass a character array as parameter to the function and use it as output parameter.


Since your string is (apparently) always 20 characters, you can simply do this:

void getString( char *outputString ) {
    // do stuff to outputString instead of mallocing, or use local memory and copy it at the end
}

char line[20];
for( ... ) {
    getString( line );
    // do things with line
}

Because this avoids many small mallocs, it is faster.


It depends.

You could decide and document that the returned string is a pointer to some static internal buffer. Then your routine is not re-entrant (nor thread-safe). For instance ctime or getpwent does that.

A better thing would be to pass the result string and size as arguments, and to fill that string and possibly return that. getcwd (or snprintf or strftime which returns a size, not a pointer) works that way.

But usually, you decide and document that the returned string is heap allocated, and it is the responsability of the caller to free it. You might want to use strdup or asprintf in that case.

And you might use in your entire program Boehm's conservative garbage collector (e.g. use its GC_STRDUP or GC_MALLOC_ATOMIC for strings, and GC_MALLOC for heap values containing some pointers.)

If you feel that standard malloc or strdup is too slow (but please measure that first), you could have your own pool allocators, etc.

You could also have alternate schemes (but it is important to document them). For example, you could return some interned string, or even a canonical interned string (sometimes called "quark" or "symbol") - then be able to use pointer equality instead of string equality. You could also have some reference counter scheme. Look for example at what Glib (from GTK, but usable outside of GUI programs!) provides: GString-s, GQuark-s, string utilities

It is however important to decide if the result is heap allocated or not, and to define clearly who has the responsibility to free (and how should it be freed) that heap-allocated result.

You may want to use valgrind to chase memory leaks. Don't forget to pass -Wall -g to your gcc compiler!

PS. I would consider using Boehm's GC. And I don't think that malloc (or strdup, asprintf ....) should be rejected for performance reasons (you could chose some other & faster malloc implementation, or use your own memory pools). However, memory leaks could be an issue.

Tags:

C

Malloc

Pointers