Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a process keep track of its local variables

As far as I know, when a process allocates local variables, it does so by pushing them onto memory as a stack, but still accesses them as random memory by using an offset from the stack pointer to reference them (from this thread What is the idea behind using a stack for local variables?).

However, how does it know which variables have what offset? Am I thinking about this in the right way?

like image 285
Christian Bouwense Avatar asked Feb 14 '18 18:02

Christian Bouwense


People also ask

How are local variables stored?

Local variables are stored in memory area of the corresponding function. Scope of a variable is a program part, in which a variable can be referred to. Variables declared inside a block (at the internal level), have the block as their scope.

What helps keep track on variable usage in our program?

For the main part it's the C compiler that keeps track. During the compilation process the compiler builds up a large data structure called the parse tree. It also keeps track of all variables, functions, types, ... everything with a name (i.e. identifier); this is called the symbol table.

How does compiler store variables?

The compiler decides where to place the six variable within this stack frame, maybe at 8 bytes from the frame start and remembers that relative position. So, the instructions that the compiler produces for the function, are: advance the stack pointer by enough bytes for all the local variables of the function.

How are local variables of a subroutine accessed within an activation record?

Local variables (including parameters) are stored in the activation record of the method in which they are declared. They are accessed at runtime using an offset from the frame pointer (FP). Since we're assuming that "up" in the stack means a lower address, these offsets will be negative numbers.


3 Answers

Offsets of local variables are "baked into" the machine code as constants. By the time the compiler is done, things that your program referred to as local variables are replaced with fixed memory offsets assigned by compiler.

Let's say you declare three local variables:

char a[8];
int b;
short c;

The compiler assigns offsets to these variables: a is at offset 0, b is at offset 8, and c is at offset 12. Let's say your code does b += c. Compiler translates this into a block of code that looks like this:

LOAD    @(SP+8)
ADD     @(SP+12)
STORE   @(SP+8)

The only value that changes here is SP (stack pointer). All offsets are numeric constants.

like image 59
Sergey Kalinichenko Avatar answered Oct 16 '22 12:10

Sergey Kalinichenko


Preface: The following text uses the x86 architecture as example. Other architectures do handle things differently.

[...] it does so by pushing them into memory as a stack, [...]

That's close. it does so by pushing them into memory ON THE stack [of the current process]. Every process has its own stack. Therefore with every context switch this Stack Frame does change - and so do its local variables (on the stack).

Usually(!) locally defined variables are referenced relative to the Stack Frame saved and present in the EBP register. This happens in contrast to globally defined varables which are referenced relative to the Data Segment Base. So every process does have its own stack with its own local variables.

Newer compilers can spare the register EBP and reference the variables relative to the ESP register. This has two consequences:

  • one register more available to use
  • one possibility less for debugging (debugging often used the EBP value as reference for the current Stack Frame to identify local variables). So this makes debugging harder without a separate debugging information file.

So to answer your main question

How does a process keep track of its local variables

Processes keep track of their Stack Frame (which contains the Local Variables), but not of their Local Variables themselves. And the Stack Frame changes with each Process Switch. The Local Variables are merely referenced relative to the Stack Frame Pointer kept in the register EBP (or relative to the Stack Pointer ESP, which depends on the compiler settings).

like image 2
zx485 Avatar answered Oct 16 '22 12:10

zx485


Compiler does the job in memorizing the offsets. These offsets are simply hardcoded. Like to load the variable to register (eg. to eax) compiler would produce something like mov eax, [esp-4], where esp is stack pointer register and 4 is the offset. If new variable will be pushed next mov to get/set variable will have bigger offset. All this is compilation time analysis.

Also, the stack on some platform may be reversed - so offset will be positive.

like image 1
Michal Butterweck Avatar answered Oct 16 '22 10:10

Michal Butterweck