Is it OK to reference an out-of-scope local variab

2019-01-27 23:00发布

In this code, I reference the local variable b even though it is out of scope. But I do it from within the same function so it's probably still on the stack, right? I ran the program and it worked but I'd like to know if it's guaranteed to work on all implementations.

#include <iostream>

void main()
{
    int* a;
    {
        int b = 5;
        a = &b;
    }
    std::cout << *a;
}

4条回答
仙女界的扛把子
2楼-- · 2019-01-27 23:41

The problem here is not that b is out of scope. It is that the lifetime of b has ended. Scope is about where the name of an object is known. Lifetime is about when the object exists (within the computational model).

Technically, the object b does not exist when you reference it with *a. The bytes that were used to represent it might happen to be still unchanged in memory, and accessing them with *a might happen to work sometimes, especially if optimization is not turned on, but it is undefined behavior.

An object can still be accessible even though its name is not in scope. Here is an example of an object that is accessible during its lifetime even though it is not in scope:

void foo(void)
{
    int b;
    bar(&b);
}

In this code, the function bar may access b, even though it cannot see the name of b in foo. Although control leaves the block in which b is created, execution of the block is merely suspended, not terminated. So b continues to exist even while the function bar is executing. So b will be out of scope, but the access will be during its lifetime.

查看更多
Summer. ? 凉城
3楼-- · 2019-01-27 23:42

No, that's not guaranteed to work. a is dangling once the inner scope is exited, so any dereference of it results in Undefined Behaviour and nothing whatsoever is guaranteed.

查看更多
我只想做你的唯一
4楼-- · 2019-01-27 23:45

The spec says

An instance of each object with automatic storage duration (3.7.3) is associated with each entry into its block. Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended (by a call of a function or receipt of a signal).

b is an object with automatic storage duration. So, when you are outside the object's block, the object does not exist anymore. You can jump before it and continue write to it, I believe, but not if you jump outside its block. That's too much stretching it.

查看更多
叼着烟拽天下
5楼-- · 2019-01-28 00:02

I put together this example to help demonstrate what's going on with memory allocation in a typical frame-based stack. See: Is the stack variable deallocated when it goes out of scope?. That question was closed as a duplicate.

In testerA, we capture the address of our local variable a for future use. We do a similar thing with testerB, only this time we capture the address of the second integer variable, b. Notice that we overwrite the memory for a with the value 44 - calling it f in this function.

You can inspect these values immediately after calling the functions to observe what's going on. We're literally re-using the same memory addresses - but there's no guarantee what format the data is in from a prior function call.

Inspecting the Stack

#include <iostream>

int* aPtr = nullptr;
int* bPtr = nullptr;

int testerA()
{
    int a = 3;
    aPtr = &a;
}

int testerB()
{
    int f = 44;
    int b = 5;
    bPtr = &b;
}

int main()
{
    using namespace std;
    testerA();
    int test1 = *aPtr;
    testerB();
    int test2 = *aPtr;
    int test3 = *bPtr;

    cout << "A: " << test1 << " -> " << test2 << endl;
    cout << "B: " << test3 << endl;

    cout << "aPtr: " << hex << aPtr << endl;
    cout << "bPtr: " << hex << bPtr << endl;

    return 0;
}

Sample Output

A: 3 -> 44
B: 5
aPtr: 0x7fff9e58609c
bPtr: 0x7fff9e586098
查看更多
登录 后发表回答