Skip to content

Commit 569a751

Browse files
author
Colin Robertson
authored
Merge pull request MicrosoftDocs#3279 from MicrosoftDocs/master637636092850540086
Repo sync for protected CLA branch
2 parents 09f9b25 + bfad80a commit 569a751

File tree

6 files changed

+140
-14
lines changed

6 files changed

+140
-14
lines changed

docs/c-runtime-library/crt-initialization.md

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22
title: "CRT Initialization"
33
description: "Describes how the CRT initializes global state in native code."
44
ms.topic: "conceptual"
5-
ms.date: "11/04/2016"
5+
ms.date: 08/02/2021
66
helpviewer_keywords: ["CRT initialization [C++]"]
77
ms.assetid: e7979813-1856-4848-9639-f29c86b74ad7
88
---
99
# CRT Initialization
1010

11-
This topic describes how the CRT initializes global state in native code.
11+
This article describes how the CRT initializes global state in native code.
1212

1313
By default, the linker includes the CRT library, which provides its own startup code. This startup code initializes the CRT library, calls global initializers, and then calls the user-provided `main` function for console applications.
1414

15+
It's possible, though not recommended, to take advantage of Microsoft-specific linker behavior to insert your own global initializers in a specific order. This code isn't portable, and comes with some important caveats.
16+
1517
## Initializing a Global Object
1618

1719
Consider the following code:
@@ -32,13 +34,13 @@ int main()
3234

3335
According to the C/C++ standard, `func()` must be called before `main()` is executed. But who calls it?
3436

35-
One way to determine the caller is to set a breakpoint in `func()`, debug the application, and examine the stack. This is possible because the CRT source code is included with Visual Studio.
37+
One way to determine the caller is to set a breakpoint in `func()`, debug the application, and examine the stack. It's possible because the CRT source code is included with Visual Studio.
3638

3739
When you browse the functions on the stack, you'll see that the CRT is calling a list of function pointers. These functions are similar to `func()`, or constructors for class instances.
3840

39-
The CRT gets the list of function pointers from the Microsoft C++ compiler. When the compiler sees a global initializer, it generates a dynamic initializer in the `.CRT$XCU` section where `CRT` is the section name and `XCU` is the group name. To get a list of dynamic initializers, run the command **dumpbin /all main.obj**, and then search the `.CRT$XCU` section. This applies when main.cpp is compiled as a C++ file, not a C file. It will be similar to the following example:
41+
The CRT gets the list of function pointers from the Microsoft C++ compiler. When the compiler sees a global initializer, it generates a dynamic initializer in the `.CRT$XCU` section where `CRT` is the section name and `XCU` is the group name. To get a list of dynamic initializers, run the command **`dumpbin /all main.obj`**, and then search the `.CRT$XCU` section. The command only applies when *`main.cpp`* is compiled as a C++ file, not a C file. It should be similar to this example:
4042

41-
```
43+
```cmd
4244
SECTION HEADER #6
4345
.CRT$XCU name
4446
0 physical address
@@ -72,11 +74,11 @@ The CRT defines two pointers:
7274

7375
Neither group has any other symbols defined except `__xc_a` and `__xc_z`.
7476

75-
Now, when the linker reads various `.CRT` groups, it combines them in one section and orders them alphabetically. This means that the user-defined global initializers (which the Microsoft C++ compiler puts in `.CRT$XCU`) will always come after `.CRT$XCA` and before `.CRT$XCZ`.
77+
Now, when the linker reads various `.CRT` subsections (the part after the `$`), it combines them in one section and orders them alphabetically. It means that the user-defined global initializers (which the Microsoft C++ compiler puts in `.CRT$XCU`) always come after `.CRT$XCA` and before `.CRT$XCZ`.
7678

77-
The section will resemble the following example:
79+
The section should resemble this example:
7880

79-
```
81+
```asm
8082
.CRT$XCA
8183
__xc_a
8284
.CRT$XCU
@@ -88,6 +90,26 @@ The section will resemble the following example:
8890

8991
So, the CRT library uses both `__xc_a` and `__xc_z` to determine the start and end of the global initializers list because of the way in which they're laid out in memory after the image is loaded.
9092

93+
## Linker features for initialization
94+
95+
The C++ Standard doesn't provide a conforming way to specify relative order across translation units for a user-supplied global initializer. However, since the Microsoft linker orders the `.CRT` subsections alphabetically, it's possible to take advantage of this ordering to specify initialization order. We don't recommend this Microsoft-specific technique, and it may break in a future release. We've documented it only to keep you from creating code that's broken in hard-to-diagnose ways.
96+
97+
To help prevent issues in your code, starting in Visual Studio 2019 version 16.11, we've added two new off by default warnings: [C5247](../error-messages/compiler-warnings/c5247.md) and [C5248](../error-messages/compiler-warnings/c5248.md). Enable these warnings to detect problems when creating your own initializers.
98+
99+
You can add initializers to unused reserved section names to create them in a specific relative order to the compiler generated dynamic initializers:
100+
101+
```cpp
102+
#pragma section(".CRT$XCT", read)
103+
// 'i1' is guaranteed to be called before any compiler generated C++ dynamic initializer
104+
__declspec(allocate(".CRT$XCT")) type i1 = f;
105+
106+
#pragma section(".CRT$XCV", read)
107+
// 'i2' is guaranteed to be called after any compiler generated C++ dynamic initializer
108+
__declspec(allocate(".CRT$XCV")) type i2 = f;
109+
```
110+
111+
The names `.CRT$XCT` and `.CRT$XCV` aren't used by either the compiler or the CRT library right now, but there's no guarantee that they'll remain unused in the future. And, your variables could still be optimized away by the compiler. Consider the potential engineering, maintenance, and portability issues before adopting this technique.
112+
91113
## See also
92114
93115
[C runtime (CRT) and C++ Standard Library (STL) `.lib` files](../c-runtime-library/crt-library-features.md)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
title: "Compiler Warning C5247"
3+
description: Compiler warning C5247 description and solution.
4+
ms.date: 08/02/2021
5+
f1_keywords: ["C5247"]
6+
helpviewer_keywords: ["C5247"]
7+
---
8+
# Compiler Warning C5247
9+
10+
> section '*section-name*' is reserved for C++ dynamic initialization. Manually creating the section will interfere with C++ dynamic initialization and may lead to undefined behavior
11+
12+
## Remarks
13+
14+
The Microsoft C++ compiler uses reserved section names for internal implementation of features such as C++ dynamic initialization. If your code creates a section with the same name as a reserved section, such as `.CRT$XCU`, it interferes with the compiler. It may prevent other dynamic initialization and cause undefined behavior.
15+
16+
To resolve this error, don't create a section that uses the reserved name.
17+
18+
There's no C++ standard conforming way to initialize variables across translation units, in a specific relative order with compiler generated dynamic initializers. Ways to force initialization before or after compiler generated C++ dynamic initializers are implementation-specific. For more information on Microsoft-specific implementation details, see [CRT initialization](../../c-runtime-library/crt-initialization.md).
19+
20+
Compiler Warning C5247 is new in Visual Studio 2019 version 16.11. It's off by default. For more information on how to enable this warning, see [Compiler warnings that are off by default](../../preprocessor/compiler-warnings-that-are-off-by-default.md).
21+
22+
## Example
23+
24+
Code that tries to emulate the C++ compiler behavior for dynamic initialization often takes this form:
25+
26+
```cpp
27+
void f();
28+
typedef void (*type)();
29+
30+
#pragma section(".CRT$XCU", read)
31+
__declspec(allocate(".CRT$XCU")) type i = f;
32+
```
33+
34+
This code creates a section using a reserved name, `.CRT$XCU`. It stops the compiler from creating the section with the expected properties, and it may skip other initializations. The variable `i` placed in the section is a regular variable, and isn't considered an initializer by the compiler. The compiler may optimize `i` away. The relative order when `f` gets called compared to other dynamic initializers is unspecified.
35+
36+
If initialization order isn't important, you can use this pattern to dynamically initialize a variable at startup:
37+
38+
```cpp
39+
void f();
40+
41+
struct init_helper {
42+
init_helper() { f(); }
43+
};
44+
45+
init_helper i;
46+
```
47+
48+
## See also
49+
50+
[CRT initialization](../../c-runtime-library/crt-initialization.md)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
title: "Compiler Warning C5248"
3+
description: Compiler warning C5248 description and solution.
4+
ms.date: 08/02/2021
5+
f1_keywords: ["C5248"]
6+
helpviewer_keywords: ["C5248"]
7+
---
8+
# Compiler Warning C5248
9+
10+
> section '*section-name*' is reserved for C++ dynamic initialization. Variables manually put into the section may be optimized out and their order relative to compiler generated dynamic initializers is unspecified
11+
12+
## Remarks
13+
14+
The Microsoft C++ compiler uses reserved section names for internal implementation of features such as C++ dynamic initialization. If your code inserts a variable in a reserved section, such as `.CRT$XCU`, it interferes with the compiler. Your variable isn't considered a C++ dynamic initializer. Also, its relative initialization order compared to compiler generated dynamic initializers isn't specified.
15+
16+
To resolve this error, don't create a section that uses the reserved name or insert a variable in the reserved section.
17+
18+
There's no C++ standard conforming way to initialize variables across translation units, in a specific relative order with compiler generated dynamic initializers. Ways to force initialization before or after compiler generated C++ dynamic initializers are implementation-specific. For more information on Microsoft-specific implementation details, see [CRT initialization](../../c-runtime-library/crt-initialization.md).
19+
20+
Compiler Warning C5248 is new in Visual Studio 2019 version 16.11. It's off by default. For more information on how to enable this warning, see [Compiler warnings that are off by default](../../preprocessor/compiler-warnings-that-are-off-by-default.md).
21+
22+
## Example
23+
24+
Code that tries to emulate the C++ compiler behavior for dynamic initialization often takes this form:
25+
26+
```cpp
27+
void f();
28+
typedef void (*type)();
29+
30+
#pragma section(".CRT$XCU", read)
31+
__declspec(allocate(".CRT$XCU")) type i = f;
32+
```
33+
34+
This code creates a section using a reserved name, `.CRT$XCU`. It stops the compiler from creating the section with the expected properties, and it may skip other initializations. The variable `i` placed in the section is a regular variable, and isn't considered an initializer by the compiler. The compiler may optimize `i` away. The relative order when `f` gets called compared to other dynamic initializers is unspecified.
35+
36+
If initialization order isn't important, you can use this pattern to dynamically initialize a variable at startup:
37+
38+
```cpp
39+
void f();
40+
41+
struct init_helper {
42+
init_helper() { f(); }
43+
};
44+
45+
init_helper i;
46+
```
47+
48+
## See also
49+
50+
[CRT initialization](../../c-runtime-library/crt-initialization.md)

docs/error-messages/compiler-warnings/compiler-warnings-c4800-through-c4999.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
title: "Compiler warnings C4800 Through C5999"
33
description: "Table of Microsoft C/C++ compiler warnings C4800 through C5999."
44
ms.date: 06/11/2021
5-
f1_keywords: ["C4808", "C4809", "C4825", "C4827", "C4837", "C4842", "C4844", "C4845", "C4846", "C4847", "C4848", "C4854", "C4855", "C4856", "C4857", "C4872", "C4880", "C4881", "C4882", "C4916", "C4921", "C4934", "C4954", "C4955", "C4963", "C4966", "C4970", "C4971", "C4973", "C4974", "C4981", "C4987", "C4988", "C4989", "C4990", "C4991", "C4992", "C4998", "C5022", "C5023", "C5024", "C5025", "C5026", "C5027", "C5028", "C5029", "C5030", "C5031", "C5032", "C5033", "C5034", "C5035", "C5036", "C5039", "C5040", "C5041", "C5042", "C5043", "C5044", "C5047", "C5048", "C5049", "C5051", "C5052", "C5053", "C5054", "C5055", "C5056", "C5057", "C5058", "C5059", "C5060", "C5061", "C5062", "C5063", "C5100", "C5101", "C5102", "C5103", "C5104", "C5106", "C5107", "C5108", "C5200", "C5201", "C5202", "C5203", "C5204", "C5205", "C5206", "C5207", "C5209", "C5210", "C5211", "C5212", "C5213", "C5214", "C5215", "C5216", "C5217", "C5218", "C5219", "C5220", "C5221", "C5222", "C5223", "C5224", "C5225", "C5226", "C5227", "C5228", "C5229", "C5230", "C5231", "C5232", "C5233", "C5234", "C5235", "C5236", "C5237", "C5238", "C5239", "C5240", "C5241", "C5242", "C5243", "C5244", "C5245", "C5246", "C5247", "C5248"]
6-
helpviewer_keywords: ["C4808", "C4809", "C4825", "C4827", "C4837", "C4842", "C4844", "C4845", "C4846", "C4847", "C4848", "C4854", "C4855", "C4856", "C4857", "C4872", "C4880", "C4881", "C4882", "C4916", "C4921", "C4934", "C4954", "C4955", "C4963", "C4966", "C4970", "C4971", "C4973", "C4974", "C4981", "C4987", "C4988", "C4989", "C4990", "C4991", "C4992", "C4998", "C5022", "C5023", "C5024", "C5025", "C5026", "C5027", "C5028", "C5029", "C5030", "C5031", "C5032", "C5033", "C5034", "C5035", "C5036", "C5039", "C5040", "C5041", "C5042", "C5043", "C5044", "C5047", "C5048", "C5049", "C5051", "C5052", "C5053", "C5054", "C5055", "C5056", "C5057", "C5058", "C5059", "C5060", "C5061", "C5062", "C5063", "C5100", "C5101", "C5102", "C5103", "C5104", "C5106", "C5107", "C5108", "C5200", "C5201", "C5202", "C5203", "C5204", "C5205", "C5206", "C5207", "C5209", "C5210", "C5211", "C5212", "C5213", "C5214", "C5215", "C5216", "C5217", "C5218", "C5219", "C5220", "C5221", "C5222", "C5223", "C5224", "C5225", "C5226", "C5227", "C5228", "C5229", "C5230", "C5231", "C5232", "C5233", "C5234", "C5235", "C5236", "C5237", "C5238", "C5239", "C5240", "C5241", "C5242", "C5243", "C5244", "C5245", "C5246", "C5247", "C5248"]
5+
f1_keywords: ["C4808", "C4809", "C4825", "C4827", "C4837", "C4842", "C4844", "C4845", "C4846", "C4847", "C4848", "C4854", "C4855", "C4856", "C4857", "C4872", "C4880", "C4881", "C4882", "C4916", "C4921", "C4934", "C4954", "C4955", "C4963", "C4966", "C4970", "C4971", "C4973", "C4974", "C4981", "C4987", "C4988", "C4989", "C4990", "C4991", "C4992", "C4998", "C5022", "C5023", "C5024", "C5025", "C5026", "C5027", "C5028", "C5029", "C5030", "C5031", "C5032", "C5033", "C5034", "C5035", "C5036", "C5039", "C5040", "C5041", "C5042", "C5043", "C5044", "C5047", "C5048", "C5049", "C5051", "C5052", "C5053", "C5054", "C5055", "C5056", "C5057", "C5058", "C5059", "C5060", "C5061", "C5062", "C5063", "C5100", "C5101", "C5102", "C5103", "C5104", "C5106", "C5107", "C5108", "C5200", "C5201", "C5202", "C5203", "C5204", "C5205", "C5206", "C5207", "C5209", "C5210", "C5211", "C5212", "C5213", "C5214", "C5215", "C5216", "C5217", "C5218", "C5219", "C5220", "C5221", "C5222", "C5223", "C5224", "C5225", "C5226", "C5227", "C5228", "C5229", "C5230", "C5231", "C5232", "C5233", "C5234", "C5235", "C5236", "C5237", "C5238", "C5239", "C5240", "C5241", "C5242", "C5243", "C5244", "C5245", "C5246"]
6+
helpviewer_keywords: ["C4808", "C4809", "C4825", "C4827", "C4837", "C4842", "C4844", "C4845", "C4846", "C4847", "C4848", "C4854", "C4855", "C4856", "C4857", "C4872", "C4880", "C4881", "C4882", "C4916", "C4921", "C4934", "C4954", "C4955", "C4963", "C4966", "C4970", "C4971", "C4973", "C4974", "C4981", "C4987", "C4988", "C4989", "C4990", "C4991", "C4992", "C4998", "C5022", "C5023", "C5024", "C5025", "C5026", "C5027", "C5028", "C5029", "C5030", "C5031", "C5032", "C5033", "C5034", "C5035", "C5036", "C5039", "C5040", "C5041", "C5042", "C5043", "C5044", "C5047", "C5048", "C5049", "C5051", "C5052", "C5053", "C5054", "C5055", "C5056", "C5057", "C5058", "C5059", "C5060", "C5061", "C5062", "C5063", "C5100", "C5101", "C5102", "C5103", "C5104", "C5106", "C5107", "C5108", "C5200", "C5201", "C5202", "C5203", "C5204", "C5205", "C5206", "C5207", "C5209", "C5210", "C5211", "C5212", "C5213", "C5214", "C5215", "C5216", "C5217", "C5218", "C5219", "C5220", "C5221", "C5222", "C5223", "C5224", "C5225", "C5226", "C5227", "C5228", "C5229", "C5230", "C5231", "C5232", "C5233", "C5234", "C5235", "C5236", "C5237", "C5238", "C5239", "C5240", "C5241", "C5242", "C5243", "C5244", "C5245", "C5246"]
77
---
88
# Compiler warnings C4800 through C5999
99

@@ -227,8 +227,8 @@ The articles in this section of the documentation explain a subset of the warnin
227227
| Compiler warning (level 1) C5244 | '#include \<*filename*>' in the purview of module '*module-name-1*' appears erroneous. Consider moving that directive before the module declaration, or replace the textual inclusion with 'import \<*module-name-2*>;'. |
228228
| Compiler warning (level 4) C5245 | '*function*': unreferenced function with internal linkage has been removed |
229229
| Compiler warning (level 1) C5246 | '*member*': the initialization of a subobject should be wrapped in braces |
230-
| Compiler warning (level 1) C5247 | section '*section-name*' is reserved for C++ dynamic initialization. Manually creating the section will interfere with C++ dynamic initialization and may lead to undefined behavior |
231-
| Compiler warning (level 1) C5248 | section '*section-name*' is reserved for C++ dynamic initialization. Variables manually put into the section may be optimized out and their order relative to compiler generated dynamic initializers is unspecified |
230+
| [Compiler warning (level 1) C5247](c5247.md) | section '*section-name*' is reserved for C++ dynamic initialization. Manually creating the section will interfere with C++ dynamic initialization and may lead to undefined behavior |
231+
| [Compiler warning (level 1) C5248](c5248.md) | section '*section-name*' is reserved for C++ dynamic initialization. Variables manually put into the section may be optimized out and their order relative to compiler generated dynamic initializers is unspecified |
232232

233233
## See also
234234

docs/error-messages/toc.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4296,6 +4296,10 @@
42964296
href: compiler-warnings/c5105.md
42974297
- name: Compiler warning (level 1) C5208
42984298
href: compiler-warnings/c5208.md
4299+
- name: Compiler warning (level 1) C5247
4300+
href: compiler-warnings/c5247.md
4301+
- name: Compiler warning (level 1) C5248
4302+
href: compiler-warnings/c5248.md
42994303
- name: Compiler warnings by compiler version
43004304
href: compiler-warnings/compiler-warnings-by-compiler-version.md
43014305
- name: Compiler warnings that are off by default

docs/preprocessor/compiler-warnings-that-are-off-by-default.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ The following warnings are turned off by default in Visual Studio 2015 and later
156156
| C5243 (level 1) | '*type-name*': using incomplete class '*class-name*' can cause potential one definition rule violation due to ABI limitation <sup>16.10</sup> |
157157
| C5245 (level 4) | '*function*': unreferenced function with internal linkage has been removed |
158158
| C5246 (level 1) | '*member*': the initialization of a subobject should be wrapped in braces <sup>16.10</sup> |
159-
| C5247 (level 1) | Section '*section-name*' is reserved for C++ dynamic initialization.<br/> Manually creating the section will interfere with C++ dynamic initialization and may lead to undefined behavior <sup>16.11</sup> |
160-
| C5248 (level 1) | Section '*section-name*' is reserved for C++ dynamic initialization.<br/> Variable manually put into the section may be optimized out and its order relative to compiler generated dynamic<br/> initializers is unspecified <sup>16.11</sup> |
159+
| [C5247 (level 1)](../error-messages/compiler-warnings/c5247.md) | Section '*section-name*' is reserved for C++ dynamic initialization. Manually creating the section will interfere with C++ dynamic initialization and may lead to undefined behavior <sup>16.11</sup> |
160+
| [C5248 (level 1)](../error-messages/compiler-warnings/c5248.md) | Section '*section-name*' is reserved for C++ dynamic initialization. Variable manually put into the section may be optimized out and its order relative to compiler generated dynamic initializers is unspecified <sup>16.11</sup> |
161161

162162
<sup>14.1</sup> This warning is available starting in Visual Studio 2015 Update 1.\
163163
<sup>14.3</sup> This warning is available starting in Visual Studio 2015 Update 3.\

0 commit comments

Comments
 (0)