infinite loop
infinite loop

Reputation: 1319

Returning a reference to local variable and its behaviour

I'm just working with the basics of C++ and tried the below lines of code,

int& func()
{
    int localnum = 10;
    return localnum;
}

int main()
{
    int &i = func();
    cout<<"value : "<<i<<endl;
    cout<<"value : "<<i<<endl;
    return 0;
}

Here, I'm returning a local variable as reference(which I shouldn't do actually, but I did it just to learn the behaviour).

I think even though the func() execution is completed the value of localnum will be still held and not destroyed until any process uses the memory space (but sets some bits/flags so that remaining process treats this memory chunk as free and can use it) - Correct me if I'm wrong

Just to check this I'm printing the value of i. In my case, this is the output

value : 10

value : 264952704

This is the same scenario even if I'm using a pointer and returning an address in place of reference.

My question is, I'm not running any process in between those prints, but still the value is getting changed. So that means any other process in my system is using the memory area of localnum in between those prints?

Upvotes: 3

Views: 93

Answers (5)

Yunnosch
Yunnosch

Reputation: 26703

The use of << implies quite a lot of activity, without needing a different process. Check the #includes you needed in the example program you are quoting from. By the way giving the whole code of that would be called a "MCVE". https://stackoverflow.com/help/mcve

Actually the only activity able to change "your" stack is the same process, even the same thread within that process. Because each process has its own stack.

The memory you are talking about is the stack. The administration data to that is not more than a pointer to the first useable part of memory; and maybe an implicit knowledge how big the stack is in total. I.e. there are no separate flags for each byte on the stack, that would add a serious amount of memory needed for the stack.

For the fact that you get the "10" only once, for the same code being executed I offer the following (compiler depending but probably common) explanation:

  • start the first line with the <<
  • read the value of i
  • put the value somewhere it will not be overwritten
    (possibly a CPU register, or somewhere safe on the stack,
    i.e. a place which is reserved for tha purpose in this activity)
  • use the stack to do the streaming to output
  • doing so overwrites the variable
  • but the value is already somewhere else and safe
  • output it successfully
  • do all that again for the second line,
    but this time the value is the overwritten one

Just to repeat what you yourself and some comments said:
Using stack after leaving a function is evil.

Upvotes: 3

CIsForCookies
CIsForCookies

Reputation: 12817

I think even though the func() execution is completed the value of localnum will be still held and not destroyed until any process uses the memory space (but sets some bits/flags so that remaining process treats this memory chunk as free and can use it) - Correct me if I'm wrong

since this is an UB, you are not entirely correct. Some compiler might set a bit/flag and some other compiler might set the value to zero... since UB gives each compiler the freedom to do what it likes your explanation is just one of many (although I think it's the most common one)

My question is, I'm not running any process in between those prints, but still the value is getting changed. So that means any other process in my system is using the memory area of localnum in between those prints?

If your process isn't doing it, and the value is changed, then, yes, someone else is changing the value. Note that even though you are not changing the value in that address directly, your code might be implemented in a way that does change it behind your back (the << operator for example, as Yunnosch said)

Here, I'm returning a local variable as reference(which I shouldn't do actually, but I did it just to learn the behaviour).

I wouldn't recommend on learning a behaviour from a UB case. It varries from machine to machine.

Upvotes: 1

A.S.H
A.S.H

Reputation: 29332

If you reason purely about the language, this is simply undefined behavior, so theoretically the result could be anything.

Following your reasoning about the implementation, there's no need for another process to overwrite a local variable, usually allocated in the stack. Among other things, any call to another function will do. In this case, your first call to the operator << of the cout object involves a function invocation, which re-used the stack area that was used by func(), resulting in overwriting the memory location where the variable localnum was temporarily created.

But again, the observed result is not consistent; it depends much on the implementation, compiler, compiler options etc..

Upvotes: 4

zhm
zhm

Reputation: 3641

It's undefined behavior, which means anything is possible. What really happens, depends on implementation of compiler.

Upvotes: 2

since int localnum is scoped to func function you are actually returning a reference to something that is no longer available after the function returns

Upvotes: 0

Related Questions