Variable remaining in memory after stack termination in a pointer returning function with a pointer argument

Hello all,

Being new to pointers and needing practice I thought I would write a simple function to try and understand them better.

This is the function I wrote:
1
2
3
4
5
int * testfunc(int * intPtr){
	int x = *intPtr;
	int* xptr = &x;
	return (xptr);
}


to test it I wrote the following. I expected an error on the last line cause the function stack (i thought) should terminate before the dereference operator is reached. The dereference operator dereferences the return pointer to the variable x inside the testfunc and because the variable x is initialized inside the function stack I expected the variable to terminate and raise an error.

1
2
3
4
5
	int n2 = 4;
	int * n2Ptr = &n2;
	cout << n2Ptr << endl;
	cout << testfunc(n2Ptr) << endl;
	cout << *testfunc(n2Ptr) << endl;


To my surprise this works fine. How does this happen?

output:

0x16b2233f0
0x16b2233b4
4


Thanks in advance!
Last edited on
Huston, we have a problem.

I'll go thru your function.
1
2
3
4
5
int * testfunc(int * intPtr){
	int x = *intPtr;	// ok: x = value pointed to be intPtr
	int* xptr = &x;		// ??: xptr has the address of local variable x
	return (xptr);		// bad: returning the address of a local variable
}


A function's local variables live on the call stack. Part of the function return process is to pop that stack.

You are returning a pointer to memory that's out of scope and may be overwritten by a future function call.
Last edited on
kbw thank you for your reply,

I don't really get how the variable x is out of the call stack, am I also passing the address of the actual parameter provided for intPtr to the variable x? I thought that the dereference operator only returned the value of the object pointed by a pointer.
First, you copy the value pointed to by the pointer intPtr into the local variable x. That's fine.

Then you create a pointer xptr to the local (stack allocated) variable x. Also perfectly fine.

But, finally, you return the pointer xptr.

Since local (stack allocated) variables, such as your x, cease to exist as soon as the function returns, the returned pointer xptr is "dangling" (invalid) at that the moment that we return to the caller!
Last edited on
kigar hello and thank you for the reply,

if the returned pointer is dangling then is the correnctness of the value printed by the last cout just a compiler specific thing?

sorry if the question is stupid : )
A pointer is really just a memory address.

A "dangling" pointer is a pointer (memory address) that is pointing to a memory location that is no longer valid. That is not a problem at all, until you actually try to dereference the "dangling" pointer!

But, as soon as you actually try to access the data that the "dangling" pointer is pointing to, then you will get undefined behavior! This means that you may read a – seemingly – correct value, or you may read some arbitrary "garbage" data, or (if you are lucky) your application crashes with an "access violation" exception.

(I consider a crash the "good" case, since at least you'll know that something is seriously wrong)
Last edited on
I get it now, thanks a lot!

marked it as solved
Does your compiler not report a warning for L4? MS VS reports:
"warning C4172: returning address of local variable or temporary: x"

Just a follow-on point. If you declare the variable static, you can do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

int* testfunc(int* intPtr) {
	static int x {};

	x = *intPtr;

	static int* xptr ;

	xptr = &x;
	return xptr;
}

int main() {
	int n2 { 4 };
	auto n2Ptr { &n2 };

	std::cout << "n2\n" << n2Ptr << '\n';
	std::cout << testfunc(n2Ptr) << '\n';
	std::cout << *testfunc(n2Ptr) << '\n';

	int n3 { 6 };
	auto n3Ptr { &n3 };

	std::cout << "\nn3\n" << n3Ptr << '\n';
	std::cout << testfunc(n3Ptr) << '\n';
	std::cout << *testfunc(n3Ptr) << '\n';

	std::cout << "\nn2\n" << n2Ptr << '\n';
	std::cout << testfunc(n2Ptr) << '\n';
	std::cout << *testfunc(n2Ptr) << '\n';
}


which is valid. Static simply in this case means that the scope of the variable is still local to the function - but the lifetime exists for the life of the program. Hence the address returned is valid for the program. Note that a static variable is only initialised once - the first time the function is executed. If the value of the static variable is to be changed, this has to be done via an assignment statement.

The output from above on my computer as 64-bit is:


n2
000000000014F910
000000013F6F5690
4

n3
000000000014F914
000000013F6F5690
6

n2
000000000014F910
000000013F6F5690
4

A famous essay on this topic: https://stackoverflow.com/a/6445794/273767
Hadn't come across it before - but worth a read. :)
Topic archived. No new replies allowed.