shivams
shivams

Reputation: 2717

Same address for static variable but different for local variable

I am trying to learn operating systems. At present i am in virtual addressing. What book says that if we have one static variable and one local variable and we update them and sleep for some time and try to print their addresses then across multiple such processes running one will get same memory address.

This is because each process feel like it has whole memory and has no control of physical memory so address will remain same among various process running at the same time. I understand this but when i run my program i am getting same address across static variables but different across local variables. With my little operating systems knowledge i am not able to understand why this is happening. This is my code

int staticvar = 0;

int main(int argc, char const *argv[])
{
  int localvar = 0;
  staticvar += 1;
  localvar += 1;
  sleep(10);
  printf("static address: %x, value: %d\n", &staticvar, staticvar );
  printf("static address: %x, value: %d\n", &localvar, localvar );
  return 0;
}

This is my output when i run three different processes simultaneously.

./a.out 
static address: 60104c, value: 1
static address: 67c6128c, value: 1

./a.out 
static address: 60104c, value: 1
static address: 89e2c11c, value: 1

./a.out 
static address: 60104c, value: 1
static address: 226e03dc, value: 1

Upvotes: 2

Views: 2100

Answers (2)

JimmyB
JimmyB

Reputation: 12610

Local variables are allocated on the stack frame of the function called. The stack frame is referenced through the stack pointer (SP) register which is initialized by the OS upon start of the process. The program uses the SP to dynamically allocate stack space and look up the values stored there. So this type of access is prepared to use a dynamic address, and knowing that, the OS can choose to initialize the process' stack frame wherever it sees fit best in the current context.

"Static" variables, on the other hand, are usually referenced by constant addresses from the compiled (assembler) code. That's why they must reside at a known-at-compile-time location.

Edit:

As someone noted, the value of the SP changes through program execution, depending on stack usage. Therefore, if you call the same funtion from different parts of the program, the address of the local variable may even be different each time.

Upvotes: 3

Pawan
Pawan

Reputation: 1615

First, int staticvar = 0; defined by you is called global variable not really a static variable. To define static variable you must add static keyword while declaring the variable, e.g. static int staticvar

Now, if you see the assembly code of your C file, you'll notice that staticvar has been referenced at compile time itself. That is the reason, you're seeing the same memory location for staticvar all the time. Same goes true for, if you have global/static variable defined also.

However, the local variable gets the memory reserved at run time in stack, which OS kernel will have control. That is why you're seeing different memory location at every run.

And this behaviour holds good even if you don't put sleep() in your code.

        .file   "test11.c"
        .local  staticvar
        .comm   staticvar,4,4
        .section        .rodata
        .align 8
.LC0:
        .string "static address: %x, value: %d\n"
.LC1:
        .string "local address: %x, value: %d\n"
        .text
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $32, %rsp
        movl    %edi, -20(%rbp)
        movq    %rsi, -32(%rbp)
        movl    $0, -4(%rbp)
        movl    staticvar(%rip), %eax
        addl    $1, %eax
        movl    %eax, staticvar(%rip)
        movl    -4(%rbp), %eax
        addl    $1, %eax
        movl    %eax, -4(%rbp)
        movl    $3, %edi
        movl    $0, %eax
        call    sleep
        movl    staticvar(%rip), %edx
        movl    $.LC0, %eax
        movl    $staticvar, %esi
        movq    %rax, %rdi
        movl    $0, %eax
        call    printf
        movl    -4(%rbp), %edx
        movl    $.LC1, %eax
        leaq    -4(%rbp), %rcx
        movq    %rcx, %rsi
        movq    %rax, %rdi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-11)"
        .section        .note.GNU-stack,"",@progbits

Upvotes: 1

Related Questions