7

Consider the following code:

char* pointerTesting(void) {

    char* test = "hello";
    return test;
}

int main() {

   char* string = pointerTesting();
   printf("string: %s\n", string);
}

This has no problem compiling and running. However, in my understanding, this shouldn't work, as the memory allocated to the test pointer is on the stack and it's destroyed when returning to main.

So the question is, how does this manages to work without a malloc in the pointerTesting() function?

trincot
  • 317,000
  • 35
  • 244
  • 286
Fisher
  • 155
  • 1
  • 5
  • 3
    See http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-go and a bunch of similar questions on this topic on stackoverflow. – jman Dec 15 '11 at 00:38
  • The *pointer* is allocated on the stack (for typical implementations), but you're not returning the pointer, only a copy if its value. It's similar to `int n = 42; return n;`. It's the allocation of what it points to that's relevant. – Keith Thompson Dec 15 '11 at 01:11

3 Answers3

16

In this case, the string "hello" is stored in global memory*. So it's already allocated.

Therefore, it's still valid when you return from the function.

However, if you did this:

char test[] = "hello";
return test;

Then no, it would not work. (undefined behavior) In this case, the string is actually a local array - which is no longer live when the function returns.

*Although this usually is the case, the standard doesn't say that it has to be stored in global memory.
But the important part is that the lifetime of a string literal is the duration of the entire program. (see comments)

Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • I'd be happier if your answer mentioned that the `"hello"` is in global memory by an accident of implementation and _not_ due to proscribed behavior in any standard. – sarnold Dec 15 '11 at 00:39
  • @sarnold Agreed, should I change it to "*usually* stored in global memory"? Or should I say "is stored *elsewhere*"? – Mysticial Dec 15 '11 at 00:41
  • I like the asterisk you've got now. :) Thanks! – sarnold Dec 15 '11 at 00:47
  • 4
    The standard doesn't use the term "global memory", and I'm not 100% sure what it means. The standard requires that the array corresponding to a string literal has static storage duration, which means that its lifetime is the entire execution of the program. (The term "global" typically refers to both lifetime and visibility.) – Keith Thompson Dec 15 '11 at 01:09
  • The answer at http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-go also provides (thanks @bowie-owens) a good explanation of the problem (also they use the term read-only section of the program). – Fisher Dec 15 '11 at 14:46
6

You're returning the value of test, which is the address of the first character in the string literal "hello" (which, like all string literals, is stored as an array of char in such a way that it's available for the lifetime of the program). If you were trying to return the address of test for later use, then yeah, you'd be running into problems.

Now the following snippet would not work:

char *pointerTesting(void)
{
  char test[] = "hello";
  return test;
}

In this case, you're trying to return the address of the first element in an array object that is local to the function, which will be invalid once the function exits. Remember that in most contexts, an expression of type "N-element array of T" will be replaced with an expression of type "pointer to T" whose value is the address of the first element in the array.

John Bode
  • 119,563
  • 19
  • 122
  • 198
2

The trick is that the memory referenced by test is not on the stack as you expect. See String literals: Where do they go? for some explanations.

Community
  • 1
  • 1
Bowie Owens
  • 2,798
  • 23
  • 20