0
int * test1() {
    int a = 4;
    int * pa = &a;
    return pa;
}

int * test2() {
    int a = 4;
    return &a;
}

What is the difference between the two functions?

The test1 function returns a value without a problem, but the test2 function generates a compile warning that the address value of the local variable can not be returned. Since the pa variable of the test1 function is also a local variable, does not the values of pa and pa disappear after the function ends? Is the variable a of the test1 function and the variable pa stored in a different memory area?

dbush
  • 205,898
  • 23
  • 218
  • 273
YunjinJang
  • 165
  • 2
  • 7
  • 1
    These functions are essentially identical, and any reasonable compiler would produce the same code for them (which will probably fail, but that's on you, not the compiler). – Lee Daniel Crocker Jul 21 '17 at 01:47
  • The second function rightfully warns you that you're attempting to return the address of a local variable that goes out of scope when the function returns. Your first function has no warning because you're returning the value of a pointer variable which isn't generally a problem, but you happen to have assigned the pointer to a local variable. But the compiler hasn't put these two pieces of information together to let you know that it's a problem. – lurker Jul 21 '17 at 02:21
  • Not clear what you are up to. Both invoke undefined behaviour. – too honest for this site Jul 21 '17 at 03:05
  • Possible duplicate of [Return address of local variable in C](https://stackoverflow.com/questions/8743411/return-address-of-local-variable-in-c) – Ajay Brahmakshatriya Jul 21 '17 at 05:25

3 Answers3

2

When a variable goes out of scope, such as a local variable in a function after the function returns, its memory can be used for other purposes. Taking the address of a local variable and then dereferencing that address after the variable is out of scope invokes undefined behavior.

Both examples above are returning the address of a local variable, and in both cases dereferencing that address invokes undefined behavior.

The compiler is able to recognize this is happening and generate a warning in the second case since the address of a is returned directly. In the first case, the compiler can't detect this because the address of a is first assigned to a pointer, then the value of that pointer is returned.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thank you for your reply. Let me ask you one more question. const char * test3() { const char * a = "ABC"; return a; } Is the above function invalid because it also returns a pointer to a local variable? – YunjinJang Jul 21 '17 at 01:52
  • 1
    @YunjinJang That is not returning the address of a local variable. It is returning the *value* of a local, which happens to contain an address, specifically the address of a string literal. String literals typically live in a read-only section of memory that is valid for the lifetime of the program. – dbush Jul 21 '17 at 02:22
1

In both functions a is an automatic variable with scope limited to the function in which it is declared. This means that the lifetime of a ends when the function returns in both cases, and referring to this object outside of its lifetime causes undefined behavior.

Even using int * pa = &a; makes no difference. Here, pa is also a local variable which no longer exists after the function returns. But it is not the variable which is returned, but the value. When the value of pa (&a in test2()) is returned, it is presumably stored in some receiving variable (a pointer to int). Dereferencing this pointer leads to undefined behavior because the pointer no longer points to an object now that a has reached the end of its lifetime.

If this appears to work in some cases, it is an accident; one possible manifestation of undefined behavior.

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • *"further attempts to use"* quibble *"refer to"* a variable that has gone out of scope is undefined. *C11 Standard - Section 6.2.4 (2)* is your reference `:)` – David C. Rankin Jul 21 '17 at 06:07
  • @DavidC.Rankin-- Hmmm. The language was clunky; should have hewn closer to the Standardese ;) Edited, hopefully in the direction of clarity.... – ad absurdum Jul 21 '17 at 06:24
  • It's funny how things stick in your mind. It must have been a couple weeks ago I wandered through that section related to another question here. In my frail memory, I recalled the standard using *access*, but checked before commenting. *'refer to*" was the winner -- although *"use"*, *"access"*, or *"refer to"* are all nebulously close to the same thing `:)` – David C. Rankin Jul 21 '17 at 07:53
0

In test1() function 'a' and 'pa' are automatic variable, 'pa' is pointing to address of 'a', and you are returning copy of 'pa'. so, here what will happen is once function execution is completed, it will remove variable 'a' and you are returning a copy of pointer to a variable which is no more available in memory. that's why you will get a warning while compiling, to remove this you can create variable 'a'as static.

In second function also variable 'a' is automatic variable, and you are returning copy of that variable. so, here it will not give any warning because here memory is not involved.

Saawaj
  • 41
  • 9