Variables

Scope & Lifetime

01. What is a Scope & Lifetime?

Scope defines the region of a program's source code where a variable is visible, resolvable, and accessible.Lifetime (or storage duration) is the actual duration of time during program execution that a variable remains allocated in the system memory.

Understanding the boundary differences between scope (a compile-time static boundary) and lifetime (a runtime execution duration) is critical to avoiding memory bugs and accessing stale data references.

02. Key Characteristics

  • Global / File Scope: Variables declared outside of any block or function. They are visible throughout the application or module.
  • Function / Local Scope: Variables declared inside a function or method. They are visible only inside that function call.
  • Block Scope: Variables declared inside arbitrary code blocks (e.g., loops, conditionals). Their visibility is confined to the surrounding curly braces {}.

03. How Languages Represent It

At runtime, variable scopes map directly to physical sections of computer memory:

  • The Stack: Local/automatic variables live on a function's call stack frame. When a function executes, its frame is pushed onto the stack. When the function returns, its stack frame is popped off, ending the lifetime of all local variables instantly.
  • The Heap: Dynamically allocated objects (using new or malloc) live in the heap. Their lifetime is independent of function scopes, surviving until explicitly deleted or reclaimed by garbage collection.
  • Static / Data Segment: Global and static variables are initialized once and reside in static program memory, lasting for the entire duration of the application.

04. Language Comparison

How block scope and lifetimes differ across languages:

  • Python: Does not support block scope. Defining a variable in an if block or for loop leaves it visible outside that block. To modify a global variable inside a function, you must declare it with the global keyword.
  • Java: Follows strict block scoping. A variable is destroyed once the execution leaves its enclosing curly braces. Shadowing method parameters or outer local variables within the same method is a compiler error.
  • JavaScript: Supports block scope via let and const. Variables declared with var are function-scoped and undergo hoisting, which makes them accessible (as undefined) even before their physical declaration line.
  • C / C++: Employs strict block scope. Local stack variables are automatically destroyed upon leaving the block. Heap allocations have a lifetime that must be manually ended (using free or delete).

05. Code Examples

Select a tab below to see how scoping and lifetimes behave:

python
# Python has function scope, NOT block scope.
# Variables declared in 'if' blocks or loops are visible outside them.
if True:
    block_var = "I leak outside the block!"

print(block_var) # Output: I leak outside the block!

# Global vs Local scope
global_count = 10

def modify_global():
    # To reassign a global variable locally, you MUST declare it 'global'
    global global_count
    global_count = 20

modify_global()
print(global_count) # Output: 20

06. Key Differences

Key comparative differences regarding scopes and variables lifetime:

LanguageBlock Scope SupportVariable ShadowingMemory Allocation Method
PythonNo (Function-Scoped)Yes (locally shadows global variables)Heap references (Garbage Collected)
JavaYes (Block-Scoped)No (for local variables in same method)Stack (primitives) / Heap (objects, GC)
JavaScriptYes (with let/const)YesHeap references (Garbage Collected)
CYes (Block-Scoped)YesStack / Heap (Manual deallocation)
C++Yes (Block-Scoped)YesStack / Heap (Manual / Smart Pointers)

07. Common Mistakes

1. Accessing Block Variables Outside Blocks in Python

In Python, because there is no block scope, writing if condition: val = 1 and then referencingval outside the if statement is syntactically allowed. However, if the condition isFalse, the variable is never initialized, throwing a runtime NameError.

2. Memory Leaks in C/C++ (Stray Lifetimes)

In C and C++, allocating memory on the heap inside a block (e.g., int* ptr = malloc(sizeof(int));) and letting the pointer ptr go out of scope without freeing it results in a memory leak. The address is lost, but the memory allocation persists in the heap.

3. JavaScript hoisting bugs with 'var'

Variables declared with var are visible outside their containing block and hoisted to the top of the function scope. This can cause unexpected collisions in loops (e.g., sharing a loop counter variable). Always use let and const to enforce block scoping.