30

What is the relation between the scope and the lifetime of a variable? If a variable is out of scope, is the memory of it allowed to be overwritten by another variable, or is the space reserved until the function is left.

I am aksing because I want to know whether the code below actually works, or whether it can be that *p might be undefined

foo() {
  int *p;
  {
    int x = 5; 
    p = &x;
  }
  int y = *p;


}
user695652
  • 4,105
  • 7
  • 40
  • 58

6 Answers6

36

What is Scope?

Scope is the region or section of code where a variable can be accessed.

What is a lifetime?

Lifetime is the time duration where an object/variable is in a valid state.

For, Automatic/Local non-static variables Lifetime is limited to their Scope.
In other words, automatic variables are automagically destroyed once the scope({,}) in which they are created ends. Hence the name automatic to begin with.

What is wrong in your code example?

So Yes your code has an Undefined Behavior.

In your example scope of *p is entire function body after it was created.
However, x is a non-static local/automatic variable and hence the lifetime of x ends with it's scope i.e the closing brace of } in which it was created, once the scope ends x does not exist. *p points to something that doesn't exist anymore.

Note that technically x does not exist beyond its scope however it might happen that the compiler did not remove the contents of x and one might be able to access contents of x beyond its scope through a pointer(as you do).However, a code which does this is not a valid C++ code. It is a code which invokes Undefined Behaviour. Which means anything can happen(you might even see value of x being intact) and one should not expect observable behaviors from such a code.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • @Als Thank you, who/how is the lifetime w.r.t. the scope managed? – user695652 Jun 21 '12 at 11:54
  • 3
    @user695652: It is managed by code generated by the compiler.The scope and lifetime rules are well defined in the C++ Standard and compiler does the job to enforce these rules. – Alok Save Jun 21 '12 at 11:57
  • Do you know how this affects the size of the caller frame in the stack. Then just assigning #localVars * their_size would allocate too much memory? – user695652 Jun 21 '12 at 12:00
  • 5
    Note that local (block scope) variables don't necessarily have automatic lifetime. You can define them to be static as well., in which case they have static lifetime. – James Kanze Jun 21 '12 at 12:09
  • @JamesKanze: Indeed, I should be more clearer and stating local non-static.I will make that change.Thanks. – Alok Save Jun 21 '12 at 12:10
  • 1
    Scope is a static property of a declaration. Lifetime is a dynamic property of an object. Their relationship is quite complex. The lifetime of the refered object doesn't necessarily ends when the execution path leaves the scope for automatic objects. Think about function call. Think about nested block with another declaration hiding the current one. And for additional complexity, think about recursive functions. – AProgrammer Jun 21 '12 at 12:36
  • "_In your example scope of `*p`.._" -- I assume you meant to say scope of `p` not `*p` – Khalida Aliyeva Aug 08 '20 at 13:38
10

C11 Section 6.2.1 Paragraph 2

For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope. Different entities designated by the same identifier either have different scopes, or are in different name spaces

.

C11 Section 6.2.4 Paragraph 2

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it.

In your case x is local to the block, and so is its lifetime, therefore x cannot be accessed by its name outside the block, also because its lifetime is limited to its block the address of x will not be reserved anymore after leaving the block, thus will result in undefined behaviour.

On the other hand, for example, say a static local variable, in this case the scope is local to the block and so we can't access by its name outside the block, but the lifetime is the entire program, so we can use the address of the variable anywhere in the program while it is running. This example should help get the difference.

Community
  • 1
  • 1
phoxis
  • 60,131
  • 14
  • 81
  • 117
  • 2
    Those quotes from the C standard are not accurate for C++. The lifetime for some types of object may start at some point after storage is guaranteed to be allocated for them and end at a point before their storage is reclaimed. – CB Bailey Jun 21 '12 at 12:06
  • @CharlesBailey: Can you give an example? I didn't know of such characteristics in C++ .Yes the quotes are from C11 standards. – phoxis Jun 21 '12 at 12:09
  • @phoxis: For example, an object of any type with non-trivial initialization or a non-trivial destructor. – CB Bailey Jun 21 '12 at 12:22
  • C and C++ are in fact different languages. The question was tagged as C++ from the very first beginning. To cite quotes from the C standard is inappropriate. I recommend to either edit your answer to contain or replace the C with appropriate C++ standard quotes or just delete the quotes. – RobertS supports Monica Cellio Jun 23 '20 at 13:46
  • "*also because its lifetime is limited to its block the address of `x` will not be reserved anymore after leaving the block, thus will result in undefined behaviour.*" -- 1. If the memory for `x` is reserved or not is implementation-dependent. To say it would be not reserved anymore - suggesting this would be according to a rule by the C++ standard - is wrong. Look at the accepted answer. - 2. "*thus will result in undefined behavior*" - What will result in undefined behavior? The statement is not proper. – RobertS supports Monica Cellio Jun 23 '20 at 13:53
8

Objects (i.e. the actual underlying things that store values) have lifetimes.

Variables (i.e. the things used to refer to objects) have scope.

Either way, y = *p invokes undefined behaviour; the object referred to by x is automatic, its lifetime ends when x goes out of scope.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 4
    To be really pedantic, *names* have scopes and are the things used to refer to objects. Variables by definition are named objects or references, so the word "variable" provides an additional tool in your kit, if you're in the business of trying to confuse people about the difference between objects and names ;-) Consider for example 3.2/1 "A variable whose name appears..." as an example of the standard using "variable" and clearly meaning the object, not the thing used to refer to the object. – Steve Jessop Jun 21 '12 at 12:08
3

What is the relation between the scope and the lifetime of a variable?

As Oli stated, variables have scope and objects lifetime. The scope of a variable and the lifetime of it are bound, but you can have objects whose lifetime extends beyond the scope on which they were created:

int* f() {
   int *p                    // Variable p
          = new int(1);      // object (call it x)
   return p;                 // p scope ends, p lifetime ends, x survives
}
int main() {
   int *q                    // Variable q
          = f();             // ... points to x
   delete q;                 // x lifetime ends, q is in scope, q is alive
}

In your particular case, x variable ends it's lifetime when the scope in which it was created is closed, so you have undefined behavior.

If a variable is out of scope, is the memory of it allowed to be overwritten by another variable, or is the space reserved until the function is left.

This is a detail of implementation. Accessing the variable is undefined behavior in all cases and because not all cases must be equal, and if the variable had a non trivial destructor, it would be called at the end of the scope, so whether the memory is there or not is irrelevant: the object is no longer there. That being said, in many cases compilers will not release the memory in the function (i.e. they will not reseat the frame pointer) when a variable goes out of scope, but they might reuse the same space to hold other variables in the same function.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
1

I have run your program and the output is 5.The output is still 5 though the x variable is destroyed after the second '}' is because the memory location is not overwritten by any other variable.if you have a lot of code after after the end of second scope,It is highly likely that the memory location previously owned by 'x' is overwritten.

int x = 5; 
*p = &x;
}  //  x lifetime ends after this.but the number '5' is still there in that memory.
   //but it is possible to assign this memory (which previously belong to x) to a new var.
tez
  • 4,990
  • 12
  • 47
  • 67
0

Standard defines that the memory is allowed to be overwritten once scope is left. Compiler implementation makes it reserved and freed. Compile-time optimizations might move allocation of stack so they will no longer reflect your order.

Your code does invoke undefined behaviour and should not be used. Your code might actually work, since writing value of y occurs AFTER taking the value p points to.

Agent_L
  • 4,960
  • 28
  • 30