Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are non-POD static values initialized? [duplicate]

Tags:

c++

static

C++, unlike some other languages, allows static data to be of any arbitrary type, not just plain-old-data. Plain-old-data is trivial to initialize (the compiler just writes the value at the appropriate address in the data segment), but the other, more complex types, are not.

How is initialization of non-POD types typically implemented in C++? In particular, what exactly happens when the function foo is executed for the first time? What mechanisms are used to keep track of whether str has already been initialized or not?

#include <string>
void foo() {
    static std::string str("Hello, Stack Overflow!");
}
like image 281
Paul Manta Avatar asked Jul 04 '14 07:07

Paul Manta


People also ask

How are static variables initialized?

Static variables are initialized only once , at the start of the execution. These variables will be initialized first, before the initialization of any instance variables. A single copy to be shared by all instances of the class. A static variable can be accessed directly by the class name and doesn't need any object.

Can static variable be initialized twice?

@heksesang: Yes, it happens only in this constellation. If I make both A and B static libs or both shared libs, I do not face the issue (c'tor of A is run only once). However, I would expect the linker to recognize and eliminate duplicate symbols and init calls.

Can static variables be re initialized?

When static keyword is used, variable or data members or functions can not be modified again. It is allocated for the lifetime of program. Static functions can be called directly by using class name. Static variables are initialized only once.

Why static variable initialized only once?

The reason for this is simple: All objects with static storage duration must be initialized (set to their initial values) before execution of main() starts. So a value which is not known at translation time cannot be used for initialization of static variables.


1 Answers

C++11 requires the initialization of function local static variables to be thread-safe. So at least in compilers that are compliant, there'll typically be some sort of synchronization primitive in use that'll need to be checked each time the function is entered.

For example, here's the assembly listing for the code from this program:

#include <string>
void foo() {
    static std::string str("Hello, Stack Overflow!");
}

int main() {}

.LC0:
    .string "Hello, Stack Overflow!"
foo():
    cmpb    $0, guard variable for foo()::str(%rip)
    je  .L14
    ret
.L14:
    pushq   %rbx
    movl    guard variable for foo()::str, %edi
    subq    $16, %rsp
    call    __cxa_guard_acquire
    testl   %eax, %eax
    jne .L15
.L1:
    addq    $16, %rsp
    popq    %rbx
    ret
.L15:
    leaq    15(%rsp), %rdx
    movl    $.LC0, %esi
    movl    foo()::str, %edi
    call    std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
    movl    guard variable for foo()::str, %edi
    call    __cxa_guard_release
    movl    $__dso_handle, %edx
    movl    foo()::str, %esi
    movl    std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string(), %edi
    call    __cxa_atexit
    jmp .L1
    movq    %rax, %rbx
    movl    guard variable for foo()::str, %edi
    call    __cxa_guard_abort
    movq    %rbx, %rdi
    call    _Unwind_Resume
main:
    xorl    %eax, %eax
    ret

The __cxa_guard_acquire, __cxa_guard_release etc. are guarding initialization of the static variable.

like image 190
Praetorian Avatar answered Sep 20 '22 01:09

Praetorian