Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

returning string from function without malloc

Tags:

c

pointers

malloc

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.

like image 711
blenzcoffee Avatar asked Mar 16 '13 20:03

blenzcoffee


People also ask

Can you free without malloc?

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.

Can you free malloc after return?

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().

Does malloc return a pointer?

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.

What does free do in malloc?

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.


4 Answers

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.

like image 140
Ivaylo Strandjev Avatar answered Sep 19 '22 13:09

Ivaylo Strandjev


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.

like image 35
Keith Thompson Avatar answered Sep 19 '22 13:09

Keith Thompson


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.

like image 36
Basile Starynkevitch Avatar answered Sep 21 '22 13:09

Basile Starynkevitch


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.

like image 43
Dave Avatar answered Sep 22 '22 13:09

Dave