Where are static variables stored in C and C++?

前端 未结 16 2076
自闭症患者
自闭症患者 2020-11-22 02:00

In what segment (.BSS, .DATA, other) of an executable file are static variables stored so that they don\'t have name collision? For example:


foo.c:                  


        
相关标签:
16条回答
  • 2020-11-22 02:38

    In fact, a variable is tuple (storage, scope, type, address, value):

    storage     :   where is it stored, for example data, stack, heap...
    scope       :   who can see us, for example global, local...
    type        :   what is our type, for example int, int*...
    address     :   where are we located
    value       :   what is our value
    

    Local scope could mean local to either the translational unit (source file), the function or the block depending on where its defined. To make variable visible to more than one function, it definitely has to be in either DATA or the BSS area (depending on whether its initialized explicitly or not, respectively). Its then scoped accordingly to either all function(s) or function(s) within source file.

    0 讨论(0)
  • 2020-11-22 02:38

    static variable stored in data segment or code segment as mentioned before.
    You can be sure that it will not be allocated on stack or heap.
    There is no risk for collision since static keyword define the scope of the variable to be a file or function, in case of collision there is a compiler/linker to warn you about.
    A nice example

    0 讨论(0)
  • 2020-11-22 02:38

    Well this question is bit too old, but since nobody points out any useful information: Check the post by 'mohit12379' explaining the store of static variables with same name in the symbol table: http://www.geekinterview.com/question_details/24745

    0 讨论(0)
  • 2020-11-22 02:39

    How to find it yourself with objdump -Sr

    To actually understand what is going on, you must understand linker relocation. If you've never touched that, consider reading this post first.

    Let's analyze a Linux x86-64 ELF example to see it ourselves:

    #include <stdio.h>
    
    int f() {
        static int i = 1;
        i++;
        return i;
    }
    
    int main() {
        printf("%d\n", f());
        printf("%d\n", f());
        return 0;
    }
    

    Compile with:

    gcc -ggdb -c main.c
    

    Decompile the code with:

    objdump -Sr main.o
    
    • -S decompiles the code with the original source intermingled
    • -r shows relocation information

    Inside the decompilation of f we see:

     static int i = 1;
     i++;
    4:  8b 05 00 00 00 00       mov    0x0(%rip),%eax        # a <f+0xa>
            6: R_X86_64_PC32    .data-0x4
    

    and the .data-0x4 says that it will go to the first byte of the .data segment.

    The -0x4 is there because we are using RIP relative addressing, thus the %rip in the instruction and R_X86_64_PC32.

    It is required because RIP points to the following instruction, which starts 4 bytes after 00 00 00 00 which is what will get relocated. I have explained this in more detail at: https://stackoverflow.com/a/30515926/895245

    Then, if we modify the source to i = 1 and do the same analysis, we conclude that:

    • static int i = 0 goes on .bss
    • static int i = 1 goes on .data
    0 讨论(0)
  • 2020-11-22 02:39

    The answer might very well depend on the compiler, so you probably want to edit your question (I mean, even the notion of segments is not mandated by ISO C nor ISO C++). For instance, on Windows an executable doesn't carry symbol names. One 'foo' would be offset 0x100, the other perhaps 0x2B0, and code from both translation units is compiled knowing the offsets for "their" foo.

    0 讨论(0)
  • 2020-11-22 02:41

    The storage location of the data will be implementation dependent.

    However, the meaning of static is "internal linkage". Thus, the symbol is internal to the compilation unit (foo.c, bar.c) and cannot be referenced outside that compilation unit. So, there can be no name collisions.

    0 讨论(0)
提交回复
热议问题