error: function returns address of local variable
Solution 1:
The local variables have a lifetime which extends only inside the block in which it is defined. The moment the control goes outside the block in which the local variable is defined, the storage for the variable is no more allocated (not guaranteed). Therefore, using the memory address of the variable outside the lifetime area of the variable will be undefined behaviour.
On the other hand you can do the following.
char *str_to_ret = malloc (sizeof (char) * required_size);
.
.
.
return str_to_ret;
And use the str_to_ret
instead. And when return
ing str_to_ret
, the address allocated by malloc
will be returned. The memory allocated by malloc
is allocated from the heap, which has a lifetime which spans the entire execution of the program. Therefore, you can access the memory location from any block and any time while the program is running.
Also note that it is a good practice that after you have done with the allocated memory block, free
it to save from memory leaks. Once you free the memory, you can't access that block again.
Solution 2:
I came up with this simple and straight-forward (i hope so) code example which should explain itself!
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* function header definitions */
char* getString(); //<- with malloc (good practice)
char * getStringNoMalloc(); //<- without malloc (fails! don't do this!)
void getStringCallByRef(char* reference); //<- callbyref (good practice)
/* the main */
int main(int argc, char*argv[]) {
//######### calling with malloc
char * a = getString();
printf("MALLOC ### a = %s \n", a);
free(a);
//######### calling without malloc
char * b = getStringNoMalloc();
printf("NO MALLOC ### b = %s \n", b); //this doesnt work, question to yourself: WHY?
//HINT: the warning says that a local reference is returned. ??!
//NO free here!
//######### call-by-reference
char c[100];
getStringCallByRef(c);
printf("CALLBYREF ### c = %s \n", c);
return 0;
}
//WITH malloc
char* getString() {
char * string;
string = malloc(sizeof(char)*100);
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
printf("string : '%s'\n", string);
return string;
}
//WITHOUT malloc (watch how it does not work this time)
char* getStringNoMalloc() {
char string[100] = {};
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", string);
return string; //but after returning.. it is NULL? :)
}
// ..and the call-by-reference way to do it (prefered)
void getStringCallByRef(char* reference) {
strcat(reference, "bla");
strcat(reference, "/");
strcat(reference, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", reference);
//OUTSIDE it is also OK because we hand over a reference defined in MAIN
// and not defined in this scope (local), which is destroyed after the function finished
}
When compiling it, you get the [intended] warning:
me@box:~$ gcc -o example.o example.c
example.c: In function ‘getStringNoMalloc’:
example.c:58:16: warning: function returns address of local variable [-Wreturn-local-addr]
return string; //but after returning.. it is NULL? :)
^~~~~~
...basically what we are discussing here!
running my example yields this output:
me@box:~$ ./example.o
string : 'bla/blub'
MALLOC ### a = bla/blub
string : 'bla/blub'
NO MALLOC ### b = (null)
string : 'bla/blub'
CALLBYREF ### c = bla/blub
Theory:
This has been answered very nicely by User @phoxis. Basically think about it this way: Everything inbetween { and } is local scope, thus by the C-Standard is "undefined" outside. By using malloc you take memory from the HEAP (programm scope) and not from the STACK (function scope) - thus its 'visible' from outside. The second correct way to do it is call-by-reference. Here you define the var inside the parent-scope, thus it is using the STACK (because the parent scope is the main()).
Summary:
3 Ways to do it, One of them false. C is kind of to clumsy to just have a function return a dynamically sized String. Either you have to malloc and then free it, or you have to call-by-reference. Or use C++ ;)
Solution 3:
Neither malloc or call by reference are needed. You can declare a pointer within the function and set it to the string/array you'd like to return.
Using @Gewure's code as the basis:
char *getStringNoMalloc(void){
char string[100] = {};
char *s_ptr = string;
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", string);
return s_ptr;
}
works perfectly.
With a non-loop version of the code in the original question:
char *foo(int x){
char a[1000];
char *a_ptr = a;
char *b = "blah";
strcpy(a, b);
return a_ptr;
}