tags:

views:

92

answers:

4

The code segment given below compiles and when run gives the result as :

$ make
gcc -g -Wall -o test test.c
$ ./test
string

/* code1 */

#include<stdio.h>
char *somefunc1()
{
   char *temp="string";
   return temp;
}
int main(int argc,char *argv[])
{
   puts(somefunc1());
   return 0;
}

whereas a slight modification to this code gives different results :

$ make
gcc -g -Wall -o test test.c
test.c: In function ‘somefunc1’:
test.c:5: warning: function returns address of local variable
$ ./test

/* code 2 */

#include<stdio.h>
char *somefunc1()
{
   char temp[] ="string";
   return temp;
}
int main(int argc,char *argv[])
{
   puts(somefunc1());
   return 0;
}

Why this is happening ?

A: 

when you do char *temp="string"; the memory for temp is allocated in heap and remains there until the execution of the program. whereas when you do char temp[] ="string"; the memory is allocated on stack, which is removed or is invalid once you are out of the scope. In your program in second case, once you are outside the function something1, the returned pointer becomes invalid. In the first case, because the array is on the heap the memory is not invalidated. But then you have successfully leaked memory.

Manoj R
Good point about the memory leak.
Jackson Pope
char *temp = "string" doesn't allocate on the heap.
JoshD
-1. There is no heap allocation going on here. Heap allocation only happens when one of the functions `malloc`, `calloc` or `realloc` is called. There is thus also no memory leak in the first program.
Bart van Ingen Schenau
+3  A: 

In the first example, you are returning the address of a string literal. This literal exists as long as the program executes, so that code is safe.

In the second example, you create a (function local) array, which is initialised to contain the string string. You then proceed to return the address of (the first element of) this array, but the array gets destroyed as soon as you leave the function. This is what your compiler warns you about. Using the pointer returned from somefunc1 results in undefined behaviour, because it does no longer refer to an existing object.

Bart van Ingen Schenau
Very good explanation (and the first correct one) +1.
JoshD
+4  A: 

char *temp = "string"; will create a pointer temp that points to a string litteral. This string literal is stored in the data segment of the executable code. It is immutable and the address is still valid after the function returns.

char temp[] = "string"; will allocate 7 characters on the stack and set them equal to 'string'. These are mutable characters. In your example, the returned value points to characters that are no longer valid when they function returns.

JoshD
s/destroyed/no longer valid/ ?
Paul R
they are indeed destroyed, how odd, I wasn't expecting that :D (p.s., I would never use char[] anyway).
Hassan Syed
@Hassan Syed: as you stated, you could declare `temp` static to preserve it after the function call, but that's not terribly great design.
JoshD
A: 

The stack variables are lost after exiting the function hence the "strange behaviour" in second case.

IronMaiden