-1
#include <stdio.h>

int* _pTest1(void) {
    int a = 10;
    int *_pA = &a;
    return _pA;
}

int* _pTest2(int a){
    int* _pA = &a;
    return _pA;
}


int main()
{
    int* _pT = _pTest1();
    printf("%d\n", *_pT);

    _pT = _pTest2(20);
    printf("%d\n", *_pT);

    return 0;
}

The Output:

1073831176
20

Why first output isn't 10, but 1073831176? What are the differences between the 'return _pA' in func _pTest1 and the 'return _pA' in func _pTest2?

akira
  • 6,050
  • 29
  • 37

2 Answers2

5

In both of your _pTest1 and _pTest2 functions, you are returning address of a local variable a, Scope/life of that is only within the function only. Accessing it variable a outside function is undefined behavior.

Note: in both function a is local to function (their memory comes from stack).

akira
  • 6,050
  • 29
  • 37
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • Both the functions have their own copy of the variable and the argument and return type in the protoypes are also different, while in `main()` 20 is passed through one function and nothing is passed through other so , how this will be an undefined behavior since none of the functions are accessing any variable outside its scope? – 0decimal0 Jul 17 '13 at 05:51
  • 1
    @PHIfounder Because you are returning address of local variable (memory for this variable is statically allocated), One you returns from function memory for all local variable became invalid. ans accessing that memory outside function is Undefined. – Grijesh Chauhan Jul 17 '13 at 05:53
  • @Grijesh Chauhan the parameter 'a' in function _pTest2 isn't a local variable? – zhangyunfeng Jul 17 '13 at 05:53
  • 1
    @zhangyunfeng yes its a local variable, Parameter variables are local variable. technically not much difference between two `a` in two functions, one its defined in parameter so that value can be passed at the time of function call. – Grijesh Chauhan Jul 17 '13 at 05:57
  • @GrijeshChauhan Then declaring it `static` can work since the variables will persist even after exiting the function. – 0decimal0 Jul 17 '13 at 05:59
  • @zhangyunfeng gcc will give you a Waring: *`returning address of local variable`* – Grijesh Chauhan Jul 17 '13 at 06:00
  • 1
    @PHIfounder: something `static` is not in the same memory region as a local variable. `static` is not the point here. – akira Jul 17 '13 at 06:00
  • 1
    @PHIfounder Diffrence between static and local variable: `Static`{ memory =static segment, initial value=0, **life=till function executes**, Scope=Within function} For `Local` = (memory=stack-segment, initial-value=garbage, **Life=till program executes**, Scope: within function), IF he returns a static-variable address then No problem. – Grijesh Chauhan Jul 17 '13 at 06:03
  • @GrijeshChauhan: the inital value of a variable depends a bit on compiler-flags. so, i kind of disagree with that aspect of your comment :) – akira Jul 17 '13 at 06:07
  • @GrijeshChauhan then the both 'a' are local variable, why the return in function _pTest2 is right? – zhangyunfeng Jul 17 '13 at 06:08
  • @akira I don't know about that compiler flag, let me know more about this, give me a link. Thanks! – Grijesh Chauhan Jul 17 '13 at 06:09
  • 1
    @zhangyunfeng: "undefined behavior" means "it might still point to somewhere in the memory where the memory was not overwritten ... YET". – akira Jul 17 '13 at 06:10
  • @zhangyunfeng Its just by-change, your code behavior is undefined you can't predict its behavior in advance, Actually your code is small so it might giving you same output for many time, write a length code and try to observe its behaviour. – Grijesh Chauhan Jul 17 '13 at 06:12
  • @akira Thanks , I got it now. – zhangyunfeng Jul 17 '13 at 06:13
  • @GrijeshChauhan Thinks , I got it now. – zhangyunfeng Jul 17 '13 at 06:14
  • @GrijeshChauhan: http://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/cpp-lin/index.htm for example, visual c has the /debug flag which alters (mainly allocated memory) variable initialization to a point, some old AIX compilers had that as well. i can't find many compilers nowadays that allow this, but iirc some years back some of them had, MIPS Pro for example has the "trap_uninitialized[=setting]" which is described as "Force all uninitialized stack, automatic and dynamically allocated variables to be initialized with 0xFFFA5A5A." – akira Jul 17 '13 at 07:33
  • 1
    VS6 http://msdn.microsoft.com/en-us/library/aa699247(v=vs.60).aspx "/GZ initializes all local variables not explicitly initialized by the program. It fills all memory used by these variables with 0xCC." in newer versions of VS that flag is named "/RTCs" which does this: "Initialization of local variables to a nonzero value." – akira Jul 17 '13 at 07:39
  • @akira Thanks for the links Akira, I will read and will caught you back. :) – Grijesh Chauhan Jul 17 '13 at 09:09
0

You're returning a local object that gets cleaned up when the function terminates.

This is undefined behaviour, anything can happen.

int _pTest1(void) {
    int a = 10; // a local object on the stack
    int *_pA = &a; // a local pointer to a local object on the stack
    return _pA;    // returning a local pointer to a local object, 
                   // wrong as the object pointed to may be cleaned up or overwritten.
}

Furthermore, in _pTest1 you probably wanted to return *_pA as at the moment you're returning a pointer even though your function signature indicates you want to return an integer.

Actually you can try a small experiment. See if it makes any difference if you return _pA as a plain pointer (return _pA;) or as a dereferenced pointer (return *_pA;). Don't forget to update the function signature and the types you assign the return of the function to.

You'll find that in the latter case the output will be consistent, whereas in the former by the time you dereference the returned address the value may be long gone.

In your second function you are returning a pointer to an argument that is not local to the function. However a in the function will still have a local address (as arguments in C are always passed by value and a local copy will be made). So returning it is still not guaranteed to result in a meaningful value.

You can prove this with the following code:

int a = 55;
printf("%p\n", &a); // this will have one address e.g. 0xbff51148
int* _pT = _pTest2(a); // _pT points to an address where a local object was held, not reliable
printf("%p\n", _pT); // this will have another address e.g. 0xbff51130
Nobilis
  • 7,310
  • 1
  • 33
  • 67
  • 1
    "You're returning a local object that gets cleaned up when the function terminates.": well, actually no: the function returns a pointer pointing to something in memory (the stack) which might get overwritten (thus "undefined content") as soon as the function ends (by other code using the stack). there is nothing "cleaned up", it might be still there or it won't. – akira Jul 17 '13 at 05:50
  • @akira True, it might be the case that immediately after the function returns the stack is not touched and the value is still there but if you make the assumption that those are cleaned up then you're not going to really on undefined behaviour. I'll add a small clarification for the sake of correctness. – Nobilis Jul 17 '13 at 05:57
  • 1
    the point is the "object that gets cleaned up" ... which is not the case. even _if_ the compiler creates code which zeroes the stack used by the function currently exited (define 'clean'), then the following code might use / overwrite / pollute the stack. nothing is cleaned here, the pointer just points to something "undefined". thats all i am saying. – akira Jul 17 '13 at 06:03
  • This is arguing semantics, I've read comments by a lot of people referring to local variables as being 'cleaned up' when you pop the stack, I think the assumption is pretty clear - don't rely on local variables. – Nobilis Jul 17 '13 at 06:09
  • correct, it's nitpicking. but in C there is no such thing as "object" and "cleaning". a c++-compiler creates code for the destructor of objects which then does some "cleaning" and when a variable goes out of scope that destructor is called. this is just not the case for C. – akira Jul 17 '13 at 06:11
  • There is such a thing as object, the context is pretty clear (that it doesn't refer to objects as in instances of classes), the standard itself talks about 'objects with static storage duration'. E.g. C99 - `6.2.4. Storage durations of objects`. – Nobilis Jul 17 '13 at 06:16