0

I can not understand, what is the difference between following function bodies

int func(void){
    int A = 20;
    return A;
}

and

int* func(void){
    int A = 20;
    return &A;
}

why returning the values does not throw the error of the segmentation fault but returning the address do?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
aTechieSmile
  • 139
  • 1
  • 1
  • 11
  • 1
    Because the address of the variable is invalid after the function returns, but the value is still valid. – William Pursell May 09 '22 at 13:44
  • Or [this answer](https://stackoverflow.com/a/13132808/2505965), which gives a good example of a [dangling pointer](https://en.wikipedia.org/wiki/Dangling_pointer). – Oka May 09 '22 at 13:46
  • @WilliamPursell , how is the value on the invalid address can be valid? – aTechieSmile May 09 '22 at 13:47
  • @Oka yes, when the function returns the address of the local variable to any function it will be a dangling pointer but how the value on that address, we can say it is valid? – aTechieSmile May 09 '22 at 13:48
  • 2
    The value 20 is valid. The fact that it was also stored in a location that is no longer valid does not invalidate it. You cannot access it through that address after the function returns, but you don't need to. The function returns the value 20 through some implementation defined mechanism (ie, in a register), and that value is accessible to the caller. If you return the address of the local variable, the caller has access to the address, but the address is invalid and the caller cannot dereference it. – William Pursell May 09 '22 at 13:53
  • When the function ends, `&A` is invalid. Even copying that address by the calling code is UB. – chux - Reinstate Monica May 09 '22 at 13:56
  • @WilliamPursell that means the copy of each local variable will be stored somewhere on the CPU registers bank for sometime after the function scope gets over or what? – aTechieSmile May 09 '22 at 14:04
  • @geeeeekyDeveloper C does not define where local variables are stored. That is an implementation defined issue. – chux - Reinstate Monica May 09 '22 at 14:07
  • 1
    @geeeeekyDeveloper No, the local variable are not stored anywhere. But the value returned by the function is given to the caller. The mechanism is implementation specific, and often that value is stored in a register. All the other local variables are lost. They *may* still be stored somewhere, but you cannot access them and for all practical purposes are discarded. – William Pursell May 09 '22 at 14:18
  • thanks!! @WilliamPursell this answered my question – aTechieSmile May 09 '22 at 14:26
  • @WilliamPursell: Re “… for all practical purposes are discarded”: This is a bad statement to teach students. Security is a practical purpose. Students must understand how computers work, in reality not just in C’s abstract model, so that they can design secure software. There are malicious people in the world who **will** take advantage of the fact that local variables are **in fact** not discarded immediately, and students must know the data is not immediately discarded. – Eric Postpischil May 09 '22 at 14:28

2 Answers2

1

Attempting to target the more specific question asked in follow-up comments on several other answers:

if the address of the local variable after the scope gets deleted then how the value of that address preserved? in case of returning local variable value from the function? this is I can not understand

Returning a value makes a copy of that value, into a storage location provided by the caller. You presumably have something like

void call_func(void) {
   int n = func();
   printf("%d\n", n);
}

as the function that calls func -- so, when func returns the value of A, that value gets copied into n.

Returning a pointer to A is actually exactly the same: a value is copied into a storage location provided by the caller. Only now the value that gets copied, is the address of the storage location formerly occupied by A.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • "Returning a pointer to A is actually exactly the same: a value is copied into a storage location provided by the caller. Only now the value that gets copied, is the address of the storage location formerly occupied by A." then why it does not throw segmentation fault for returning the value but it does for returning an address of it ? – aTechieSmile May 09 '22 at 14:13
  • 1
    Because the value is different! In one case you copy the number you actually want, in the other case you copy the address of the storage location that used to hold the number you want. The copied number can be used directly, but the copied address has to be "dereferenced" to get the number, and by the time `call_func` gets around to doing that, it's too late, and the program crashes. (Note: It's already too late the moment `func` returns; it is not possible to make the storage location stick around long enough for `call_func` to access it.) – zwol May 09 '22 at 14:58
0

A local variable with automatic storage duration is not alive after exiting the scope of the function where it is defined. So the returned pointer will be invalid and de-referencing such a pointer invokes undefined behavior.

If you will change the second function the following way

int* func(void){
    static int A = 20;
    return &A;
}

then returning a pointer to the variable A will be correct because the variable having static storage duration will be alive after exiting the function.

A returned value can be assigned to a variable or discarded. So there is nothing wrong.

Darth-CodeX
  • 2,166
  • 1
  • 6
  • 23
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • this is correct, but if the address of the local variable after the scope gets deleted then how the value of that address preserved? in case of returning local variable value from the function? this is I can not understand – aTechieSmile May 09 '22 at 13:51
  • @geeeeekyDeveloper The address of the variable will not be discarded. It is the variable itself that can be discarded. That is its memory can be already overwritten. So the returned pointer will be invalid because it does not point to an alive object. – Vlad from Moscow May 09 '22 at 13:53
  • yes, this is I understand. that the memory address will be invalid for the pointers as the function scope gets over, but how this value is still valid ? – aTechieSmile May 09 '22 at 14:05
  • @geeeeekyDeveloper The value is invalid. But what you are returning even an invalid value that will be returned. – Vlad from Moscow May 09 '22 at 14:07
  • @geeeeekyDeveloper: Re “how this value is still valid ?”: When computing `x*y + z`, the compiler or the computer does not create a new variable to hold the result of `x*y` while it adds `z`. The computer has registers we use to hold variables while doing calculations and other computations. When a `return` statement inside a function is executed, the value being returned is put into one of those registers, or some other special place designated for the function to return a value, and it remains in that place while the function returns to its caller. (Except optimization may change things.) – Eric Postpischil May 09 '22 at 14:31