Is it possible to return string from a function without calling malloc
?
I have a function as below:
char* getString(){
char tempStr[20]
// open file, read char by char and assign to tempStr
// ....
char* str = (char*)malloc(sizeof(char)*20);
strcpy(str, tempStr); // assume this copy the null terminating char as well
return str;
}
And then when I call the getString()
, I assign the return value to a char*
, and then free it when I'm done, just like below:
void randomFunction(){
char* line = NULL;
int i = 0;
while (i < 1000) {
line = getString();
// do stuff with line
free (line);
line = NULL;
}
}
However, I am wondering if there is any way to do this without malloc
? And, is this the proper way of returning string from a C function?
I tried to do some research regarding how to return without malloc
, but didn't find clear answers. I am new to C and still learning.
Actually you can use free without calling malloc , but only if the value you pass to free is a null pointer. So not useful if what you want is a pointer which might point to an allocated block, but might point to a local array.
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free(). The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc(), or realloc().
malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. To return a pointer to a type other than void , use a type cast on the return value.
The free() function in C++ deallocates a block of memory previously allocated using calloc, malloc or realloc functions, making it available for further allocations. The free() function does not change the value of the pointer, that is it still points to the same memory location.
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.
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.)
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With