Domanda

Let's say I have a static reference to a static object or primitive in the global namespace (or any other namespace):

int a = 2;
int& b = a;

int main(int argc, char** argv) {
    b++;

    return b;
}

This is a very basic example, but what does a compiler usually do with this code? Will the resulting machine code actually traverse a pointer to read/write a, or will the compiler just insert the address of a in place of b?

È stato utile?

Soluzione

The answer to this will obviously be compiler specific. I decided to try with clang-500.2.79 on x86-64 and with the -O3 flag. As given, your source yields:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
 Ltmp4:
    .cfi_def_cfa_register %rbp
    movl    _a(%rip), %eax
    incl    %eax
    movl    %eax, _a(%rip)
    popq    %rbp
    ret
    .cfi_endproc

    .section    __DATA,__data
    .globl  _a                      ## @a
    .align  2
_a:
    .long   2                       ## 0x2

    .section    __DATA,__const
    .globl  _b                      ## @b
    .align  3
_b:
    .quad   _a

As you can see, both the symbols a and b are retained (munged to _a and _b); this is required because these symbols have global linkage.

If you change your code slightly, to declare a and b as static, the result is quite different:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    movl    $3, %eax
    popq    %rbp
    ret
    .cfi_endproc

In this case, the compiler is able to optimize a and b away completely and just have main return the constant 3, because there's no way that another compilation unit can screw with the values.

Altri suggerimenti

I try to disassamble following code,

int pranit = 2;
int& sumit = pranit;

int main(int argc, char** argv) {
    sumit++;

    return sumit;
}

And following instruction suggest pranit has address of sumit.

013B13C8    8B15 04803B01   MOV EDX,DWORD PTR [sumit]                ; ConsoleA.pranit

Moreover both variables have different address,

Names in ConsoleA, item 313
 Address=013B8004
 Section=.data
 Type=Library
 Name=sumit

Names in ConsoleA, item 257
 Address=013B8000
 Section=.data
 Type=Library
 Name=pranit

I have used OllyDbg as disassembler.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top