C++中全局变量和静态成员变量的动态初始化实现

10
我对C++中变量初始化的实现方式在链接和可执行模块加载过程中有一些疑问,主要关注全局变量和静态成员变量的动态初始化,其中初始化过程涉及代码的执行。我希望回答能够针对Windows和Linux两种操作系统来解答我的问题。
对于静态初始化,我已经了解到以下几点:
- 初始值在编译期间被放置在自己的部分 - 这些部分由操作系统模块加载器映射到内存中 - 变量通过DIR32类型的重定位被赋予初始值内存地址的位置
以下是我的问题:
  1. 编译器会向生成的目标文件中添加哪些与全局变量的动态初始化相关的信息以供链接器使用?请详细描述相关部分和生成的符号。相比于非静态全局变量,静态成员变量有何不同?
  2. 链接器在链接过程中会向最终的链接模块中添加哪些信息,以便操作系统模块加载器能够正确地初始化所有变量(包括作为初始化的一部分调用函数的动态初始化的全局/静态成员变量)?
  3. 需要在动态变量初始化期间执行的函数如何映射到需要使用该代码进行初始化的特定变量?
  4. 当可执行文件或动态链接模块被加载时,如何执行变量的动态初始化?
  5. C++11常量表达式(由constexpr关键字标记)的实现是否涉及与常规静态成员变量和函数的实现有所不同的特殊注意事项?
我希望答案能够涉及一个具体的示例,以在上述问题的框架内说明如何从一个目标文件中获取相关部分/符号,并如何将这些代码链接和加载,以便正确地初始化静态变量。这个示例是针对Windows使用MSVC编译器的,请在存在差异的情况下提到gcc/linux。
以下是一段简单的C ++代码示例,涉及一个普通变量和一个静态成员变量,根据我的理解,在main之前需要由操作系统加载器进行动态初始化,因为它作为其初始化的一部分调用了一个函数:
class Test
{
public:

    static int testFunction()
    {
        return 10;
    }

    static int memberVar;
};

int Test::memberVar = Test::testFunction();

int foo()
{
    return 5;
}

int var = foo();


int main(int argc, char* argv[])
{
    var;

    Test::memberVar;

    return 0;
}

以下是使用上述代码在MSVC编译的调试模式下生成的目标文件的部分和符号转储(此转储是由llvm-readobj创建的实用程序,该实用程序随llvm / clang一起提供):

这里是使用上述代码在MSVC编译的调试模式下生成的目标文件的部分和符号转储(该转储是由llvm-readobj创建的实用程序,该实用程序随llvm / clang一起提供):

File: Source.obj
Format: COFF-i386
Arch: i386
AddressSize: 32bit
Sections [
  Section {
    Number: 1
    Name: .drectve (2E 64 72 65 63 74 76 65)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 65
    PointerToRawData: 0x2BC
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0x100A00)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_LNK_INFO (0x200)
      IMAGE_SCN_LNK_REMOVE (0x800)
    ]
  }
  Section {
    Number: 2
    Name: .debug$S (2E 64 65 62 75 67 24 53)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 3380
    PointerToRawData: 0x2FD
    PointerToRelocations: 0x1031
    PointerToLineNumbers: 0x0
    RelocationCount: 8
    LineNumberCount: 0
    Characteristics [ (0x42100040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 3
    Name: .debug$T (2E 64 65 62 75 67 24 54)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 136
    PointerToRawData: 0x1081
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0x42100040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 4
    Name: .text$di (2E 74 65 78 74 24 64 69)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 60
    PointerToRawData: 0x1109
    PointerToRelocations: 0x1145
    PointerToLineNumbers: 0x0
    RelocationCount: 3
    LineNumberCount: 0
    Characteristics [ (0x60501020)
      IMAGE_SCN_ALIGN_16BYTES (0x500000)
      IMAGE_SCN_CNT_CODE (0x20)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_EXECUTE (0x20000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 5
    Name: .debug$S (2E 64 65 62 75 67 24 53)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 216
    PointerToRawData: 0x1163
    PointerToRelocations: 0x123B
    PointerToLineNumbers: 0x0
    RelocationCount: 5
    LineNumberCount: 0
    Characteristics [ (0x42101040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 6
    Name: .text$di (2E 74 65 78 74 24 64 69)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 60
    PointerToRawData: 0x126D
    PointerToRelocations: 0x12A9
    PointerToLineNumbers: 0x0
    RelocationCount: 3
    LineNumberCount: 0
    Characteristics [ (0x60501020)
      IMAGE_SCN_ALIGN_16BYTES (0x500000)
      IMAGE_SCN_CNT_CODE (0x20)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_EXECUTE (0x20000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 7
    Name: .debug$S (2E 64 65 62 75 67 24 53)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 204
    PointerToRawData: 0x12C7
    PointerToRelocations: 0x1393
    PointerToLineNumbers: 0x0
    RelocationCount: 5
    LineNumberCount: 0
    Characteristics [ (0x42101040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 8
    Name: .text$mn (2E 74 65 78 74 24 6D 6E)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 42
    PointerToRawData: 0x13C5
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0x60501020)
      IMAGE_SCN_ALIGN_16BYTES (0x500000)
      IMAGE_SCN_CNT_CODE (0x20)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_EXECUTE (0x20000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 9
    Name: .debug$S (2E 64 65 62 75 67 24 53)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 192
    PointerToRawData: 0x13EF
    PointerToRelocations: 0x14AF
    PointerToLineNumbers: 0x0
    RelocationCount: 5
    LineNumberCount: 0
    Characteristics [ (0x42101040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 10
    Name: .text$mn (2E 74 65 78 74 24 6D 6E)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 42
    PointerToRawData: 0x14E1
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0x60501020)
      IMAGE_SCN_ALIGN_16BYTES (0x500000)
      IMAGE_SCN_CNT_CODE (0x20)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_EXECUTE (0x20000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 11
    Name: .debug$S (2E 64 65 62 75 67 24 53)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 204
    PointerToRawData: 0x150B
    PointerToRelocations: 0x15D7
    PointerToLineNumbers: 0x0
    RelocationCount: 5
    LineNumberCount: 0
    Characteristics [ (0x42101040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 12
    Name: .text$mn (2E 74 65 78 74 24 6D 6E)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 39
    PointerToRawData: 0x1609
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0x60501020)
      IMAGE_SCN_ALIGN_16BYTES (0x500000)
      IMAGE_SCN_CNT_CODE (0x20)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_EXECUTE (0x20000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 13
    Name: .debug$S (2E 64 65 62 75 67 24 53)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 224
    PointerToRawData: 0x1630
    PointerToRelocations: 0x1710
    PointerToLineNumbers: 0x0
    RelocationCount: 5
    LineNumberCount: 0
    Characteristics [ (0x42101040)
      IMAGE_SCN_ALIGN_1BYTES (0x100000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 14
    Name: .bss (2E 62 73 73 00 00 00 00)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 8
    PointerToRawData: 0x0
    PointerToRelocations: 0x0
    PointerToLineNumbers: 0x0
    RelocationCount: 0
    LineNumberCount: 0
    Characteristics [ (0xC0300080)
      IMAGE_SCN_ALIGN_4BYTES (0x300000)
      IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80)
      IMAGE_SCN_MEM_READ (0x40000000)
      IMAGE_SCN_MEM_WRITE (0x80000000)
    ]
  }
  Section {
    Number: 15
    Name: .rtc$IMZ (2E 72 74 63 24 49 4D 5A)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 4
    PointerToRawData: 0x1742
    PointerToRelocations: 0x1746
    PointerToLineNumbers: 0x0
    RelocationCount: 1
    LineNumberCount: 0
    Characteristics [ (0x40301040)
      IMAGE_SCN_ALIGN_4BYTES (0x300000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 16
    Name: .rtc$TMZ (2E 72 74 63 24 54 4D 5A)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 4
    PointerToRawData: 0x1750
    PointerToRelocations: 0x1754
    PointerToLineNumbers: 0x0
    RelocationCount: 1
    LineNumberCount: 0
    Characteristics [ (0x40301040)
      IMAGE_SCN_ALIGN_4BYTES (0x300000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_LNK_COMDAT (0x1000)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
  Section {
    Number: 17
    Name: .CRT$XCU (2E 43 52 54 24 58 43 55)
    VirtualSize: 0x0
    VirtualAddress: 0x0
    RawDataSize: 8
    PointerToRawData: 0x175E
    PointerToRelocations: 0x1766
    PointerToLineNumbers: 0x0
    RelocationCount: 2
    LineNumberCount: 0
    Characteristics [ (0x40300040)
      IMAGE_SCN_ALIGN_4BYTES (0x300000)
      IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
      IMAGE_SCN_MEM_READ (0x40000000)
    ]
  }
]
Symbols [
  Symbol {
    Name: @comp.id
    Value: 14776701
    Section: IMAGE_SYM_ABSOLUTE (-1)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: @feat.00
    Value: 2147484049
    Section: IMAGE_SYM_ABSOLUTE (-1)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: .drectve
    Value: 0
    Section: .drectve (1)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 65
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
    AuxSectionDef {
      Length: 0
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$S
    Value: 0
    Section: .debug$S (2)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 3380
      RelocationCount: 8
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
    AuxSectionDef {
      Length: 112874624
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$T
    Value: 0
    Section: .debug$T (3)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 136
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
    AuxSectionDef {
      Length: 0
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .text$di
    Value: 0
    Section: .text$di (4)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 60
      RelocationCount: 3
      LineNumberCount: 0
      Checksum: 0x46C8586B
      Number: 0
      Selection: Any (0x2)
    }
    AuxSectionDef {
      Length: 2651074843
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$S
    Value: 0
    Section: .debug$S (5)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 216
      RelocationCount: 5
      LineNumberCount: 0
      Checksum: 0x0
      Number: 4
      Selection: Associative (0x5)
      AssocSection: .text$di (4)
    }
    AuxSectionDef {
      Length: 726561912
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .text$di
    Value: 0
    Section: .text$di (6)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 60
      RelocationCount: 3
      LineNumberCount: 0
      Checksum: 0x46C8586B
      Number: 0
      Selection: Any (0x2)
    }
    AuxSectionDef {
      Length: 1313174712
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$S
    Value: 0
    Section: .debug$S (7)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 204
      RelocationCount: 5
      LineNumberCount: 0
      Checksum: 0x0
      Number: 6
      Selection: Associative (0x5)
      AssocSection: .text$di (6)
    }
    AuxSectionDef {
      Length: 3135640214
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .text$mn
    Value: 0
    Section: .text$mn (8)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 42
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0xB9575122
      Number: 0
      Selection: NoDuplicates (0x1)
    }
    AuxSectionDef {
      Length: 936864182
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$S
    Value: 0
    Section: .debug$S (9)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 192
      RelocationCount: 5
      LineNumberCount: 0
      Checksum: 0x0
      Number: 8
      Selection: Associative (0x5)
      AssocSection: .text$mn (8)
    }
    AuxSectionDef {
      Length: 3843792410
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .text$mn
    Value: 0
    Section: .text$mn (10)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 42
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x2AAFA5E4
      Number: 0
      Selection: Any (0x2)
    }
    AuxSectionDef {
      Length: 919462443
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$S
    Value: 0
    Section: .debug$S (11)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 204
      RelocationCount: 5
      LineNumberCount: 0
      Checksum: 0x0
      Number: 10
      Selection: Associative (0x5)
      AssocSection: .text$mn (10)
    }
    AuxSectionDef {
      Length: 1658743834
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .text$mn
    Value: 0
    Section: .text$mn (12)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 39
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x9F9044F9
      Number: 0
      Selection: NoDuplicates (0x1)
    }
    AuxSectionDef {
      Length: 607079010
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: .debug$S
    Value: 0
    Section: .debug$S (13)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 224
      RelocationCount: 5
      LineNumberCount: 0
      Checksum: 0x0
      Number: 12
      Selection: Associative (0x5)
      AssocSection: .text$mn (12)
    }
    AuxSectionDef {
      Length: 3159278302
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: ?testFunction@Test@@SAHXZ
    Value: 0
    Section: .text$mn (10)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: ??__E?memberVar@Test@@2HA@@YAXXZ
    Value: 0
    Section: .text$di (4)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: ?foo@@YAHXZ
    Value: 0
    Section: .text$mn (8)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: ??__Evar@@YAXXZ
    Value: 0
    Section: .text$di (6)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: _main
    Value: 0
    Section: .text$mn (12)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: __RTC_CheckEsp
    Value: 0
    Section: IMAGE_SYM_UNDEFINED (0)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: __RTC_InitBase
    Value: 0
    Section: IMAGE_SYM_UNDEFINED (0)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: __RTC_Shutdown
    Value: 0
    Section: IMAGE_SYM_UNDEFINED (0)
    BaseType: Null (0x0)
    ComplexType: Function (0x2)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: .bss
    Value: 0
    Section: .bss (14)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 8
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
    AuxSectionDef {
      Length: 0
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: ?memberVar@Test@@2HA
    Value: 4
    Section: .bss (14)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: ?var@@3HA
    Value: 0
    Section: .bss (14)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: External (0x2)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: .rtc$IMZ
    Value: 0
    Section: .rtc$IMZ (15)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 4
      RelocationCount: 1
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: Any (0x2)
    }
    AuxSectionDef {
      Length: 1569749662
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: __RTC_InitBase.rtc$IMZ
    Value: 0
    Section: .rtc$IMZ (15)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: .rtc$TMZ
    Value: 0
    Section: .rtc$TMZ (16)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 4
      RelocationCount: 1
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: Any (0x2)
    }
    AuxSectionDef {
      Length: 1278087628
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: __RTC_Shutdown.rtc$TMZ
    Value: 0
    Section: .rtc$TMZ (16)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: .CRT$XCU
    Value: 0
    Section: .CRT$XCU (17)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 2
    AuxSectionDef {
      Length: 8
      RelocationCount: 2
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
    AuxSectionDef {
      Length: 3724741121
      RelocationCount: 0
      LineNumberCount: 0
      Checksum: 0x0
      Number: 0
      Selection: 0x0
    }
  }
  Symbol {
    Name: ?memberVar$initializer$@Test@@2P6AXXZA
    Value: 0
    Section: .CRT$XCU (17)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
  Symbol {
    Name: _var$initializer$
    Value: 4
    Section: .CRT$XCU (17)
    BaseType: Null (0x0)
    ComplexType: Null (0x0)
    StorageClass: Static (0x3)
    AuxSymbolCount: 0
  }
]

非常感谢您考虑我的问题;如果能够得到详细的答案,我将不胜感激。

5
我不确定,但我认为您误解了静态函数。静态函数是仅对同一文件(翻译单元)中的其他函数可见的函数。它们与静态数据之间除了关键字“static”以外没有任何关系。 - Jonathan Potter
3
var需要动态初始化,因为它的初始值不是常量表达式(它调用了一个非constexpr函数)。如上面的注释所说,这个函数是否为static完全无关紧要。变量是否为static也完全无关紧要。你的问题是关于具有“静态存储期”的变量,但是所有全局变量(除了线程局部变量)都具有静态存储期,不仅仅是标记为static的变量。 - Jonathan Wakely
1
你在前四个问题中所询问的是具体实现相关的。你想了解关于Windows和Linux的这些细节吗?你基本上在问两个不同的问题:Windows的所有这些细节是什么,Linux的所有这些细节是什么。 - CrazyCasta
Jonathan Wakely,你说得对,我已经根据你的评论调整了问题。 - Sanee Berlow
CrazyCasta,我正在寻找Linux和Windows的详细信息。修改了问题以使其更清晰明了。 - Sanee Berlow
显示剩余2条评论
1个回答

2
这不是一个链接问题,而是一个编译器/运行时问题。当然,完整的答案因系统而异,但对于Linux上的gcc/clang来说,大致如下。我把你的小例子程序复制到基于clang的 ELLCC演示中,并为ARM编译它。我必须关闭优化才能看到有趣的东西,因为你初始化的变量没有被使用。
通过查看汇编代码,你会发现编译器将生成代码来执行源文件中需要执行的任何初始化操作。正如你所指出的,那些初始化为链接时常量值的内容可以通过将适当的符号及其初始值放入一个部分(通常称为.data用于可写的内容和.const用于只读的内容)来进行初始化。无法在编译或链接时计算的值由编译器生成的函数初始化,在进入main()之前执行。如果你编译你的示例并查看汇编代码,在末尾会有几行代码看起来像这样:
.section    .init_array,"aw",%init_array
.align  2
.long   _GLOBAL__sub_I__6873_0.cc(target1)

这里的魔法在于,.init_array 节是编译器和运行时系统有特殊意义的节。编译器将一个内部生成的函数的地址放置在 .init_array 节中。该函数执行此源文件需要的任何初始化。如果源文件中有静态 C++ 构造函数,它们也会从这里调用。x86 处理器有一个类似的节叫做 .ctors,具有类似的语义。
现在到了运行时部分。程序启动时,运行时系统首先获得控制权。它执行诸如初始化库、加载动态库等操作,然后遍历.init_array 中的每个函数指针并执行它。这样可以使您的变量初始化。
请注意,链接器实际上不必做任何事情,除了将 .init_array 中的所有函数指针聚集在一个地方,以便运行时系统可以找到它们。
正如你现在可能已经猜到的那样,还有另一个叫做 .fini_array(或 x86 世界中的 .dtors)的节,用于处理全局析构函数,当程序尝试退出时使用。

1
非常感谢你,Richard。由于你提供的信息,我已经成功实现了动态初始化。在你提供的信息基础上,我还找到了有关MSVC动态初始化的其他信息,链接如下:https://msdn.microsoft.com/en-us/library/bb918180.aspx 和 http://www.gonwan.com/?p=9。这些文章解释了CRT在main函数之前调用函数指针数组(正如你所描述的)。在MSVC下,.CRT$XCU部分包含负责初始化的函数。你的帖子对我找到正确方向起到了关键作用,非常感谢! - Sanee Berlow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接