You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enables experimental compiler support for C++ Standard modules. This option is obsolete in Visual Studio version 16.11 and later.
10
+
Enables experimental compiler support for C++ Standard modules. This option is obsolete for C++20 standard modules in Visual Studio version 16.11 and later. It's still required (along with [`/std:c++latest`](std-specify-language-standard-version.md)) for the experimental Standard library modules.
Copy file name to clipboardExpand all lines: docs/build/walkthrough-compile-a-c-program-on-the-command-line.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -61,7 +61,7 @@ If you've installed Microsoft Visual C++ Build Tools 2015 on Windows 10 or later
61
61
62
62
If you're using a different version of Windows, look in your Start menu or Start page for a Visual Studio tools folder that contains a developer command prompt shortcut. You can also use the Windows search function to search for "developer command prompt" and choose one that matches your installed version of Visual Studio. Use the shortcut to open the command prompt window.
63
63
64
-
Next, verify that the Visual C++ developer command prompt is set up correctly. In the command prompt window, enter `cl`and verify that the output looks something like this:
64
+
Next, verify that the Visual C++ developer command prompt is set up correctly. In the command prompt window, enter `cl`(or `CL`, case doesn't matter for the compiler name, but it does matter for compiler options). The output should look something like this:
Copy file name to clipboardExpand all lines: docs/code-quality/best-practices-and-examples-sal.md
+47-35Lines changed: 47 additions & 35 deletions
Original file line number
Diff line number
Diff line change
@@ -1,18 +1,19 @@
1
1
---
2
-
description: "Learn more about: Best Practices and Examples (SAL)"
3
-
title: Best Practices and Examples (SAL)
4
-
ms.date: 11/04/2016
2
+
description: "Learn more about: Best practices and examples (SAL)"
3
+
title: Best practices and examples (SAL)
4
+
ms.date: 01/27/2022
5
5
ms.topic: "conceptual"
6
6
---
7
-
# Best Practices and Examples (SAL)
7
+
# Best practices and examples (SAL)
8
8
9
9
Here are some ways to get the most out of the Source Code Annotation Language (SAL) and avoid some common problems.
10
10
11
-
## \_In\_
11
+
## `_In_`
12
12
13
-
If the function is supposed to write to the element, use `_Inout_` instead of `_In_`. This is particularly relevant in cases of automated conversion from older macros to SAL. Prior to SAL, many programmers used macros as comments—macros that were named `IN`, `OUT`, `IN_OUT`, or variants of these names. Although we recommend that you convert these macros to SAL, we also urge you to be careful when you convert them because the code might have changed since the original prototype was written and the old macro might no longer reflect what the code does. Be especially careful about the `OPTIONAL` comment macro because it is frequently placed incorrectly—for example, on the wrong side of a comma.
13
+
If the function is supposed to write to the element, use `_Inout_` instead of `_In_`. This is particularly relevant in cases of automated conversion from older macros to SAL. Prior to SAL, many programmers used macros as comments—macros that were named `IN`, `OUT`, `IN_OUT`, or variants of these names. Although we recommend that you convert these macros to SAL, we also urge you to be careful when you convert them because the code might have changed since the original prototype was written and the old macro might no longer reflect what the code does. Be especially careful about the `OPTIONAL` comment macro because it's frequently placed incorrectly—for example, on the wrong side of a comma.
14
14
15
15
```cpp
16
+
#include<sal.h>
16
17
17
18
// Incorrect
18
19
voidFunc1(_In_ int *p1)
@@ -33,11 +34,12 @@ void Func2(_Inout_ PCHAR p1)
33
34
}
34
35
```
35
36
36
-
## \_opt\_
37
+
## `_opt_`
37
38
38
-
If the caller is not allowed to pass in a null pointer, use `_In_` or `_Out_` instead of `_In_opt_` or `_Out_opt_`. This applies even to a function that checks its parameters and returns an error if it is NULL when it should not be. Although having a function check its parameter for unexpected NULL and return gracefully is a good defensive coding practice, it does not mean that the parameter annotation can be of an optional type (`_*Xxx*_opt_`).
39
+
If the caller isn't allowed to pass in a null pointer, use `_In_` or `_Out_` instead of `_In_opt_` or `_Out_opt_`. This applies even to a function that checks its parameters and returns an error if it is `NULL` when it shouldn't be. Although having a function check its parameter for unexpected `NULL` and return gracefully is a good defensive coding practice, it doesn't mean that the parameter annotation can be of an optional type (`_*Xxx*_opt_`).
39
40
40
41
```cpp
42
+
#include <sal.h>
41
43
42
44
// Incorrect
43
45
void Func1(_Out_opt_ int *p1)
@@ -52,27 +54,29 @@ void Func2(_Out_ int *p1)
52
54
}
53
55
```
54
56
55
-
## \_Pre\_defensive\_ and \_Post\_defensive\_
57
+
## `_Pre_defensive_` and `_Post_defensive_`
56
58
57
-
If a function appears at a trust boundary, we recommend that you use the `_Pre_defensive_` annotation. The "defensive" modifier modifies certain annotations to indicate that, at the point of call, the interface should be checked strictly, but in the implementation body it should assume that incorrect parameters might be passed. In that case, `_In_ _Pre_defensive_` is preferred at a trust boundary to indicate that although a caller will get an error if it attempts to pass NULL, the function body will be analyzed as if the parameter might be NULL, and any attempts to de-reference the pointer without first checking it for NULL will be flagged. A `_Post_defensive_` annotation is also available, for use in callbacks where the trusted party is assumed to be the caller and the untrusted code is the called code.
59
+
If a function appears at a trust boundary, we recommend that you use the `_Pre_defensive_` annotation. The "defensive" modifier modifies certain annotations to indicate that, at the point of call, the interface should be checked strictly, but in the implementation body it should assume that incorrect parameters might be passed. In that case, `_In_ _Pre_defensive_` is preferred at a trust boundary to indicate that although a caller will get an error if it attempts to pass `NULL`, the function body will be analyzed as if the parameter might be `NULL`, and any attempts to de-reference the pointer without first checking it for `NULL` will be flagged. A `_Post_defensive_` annotation is also available, for use in callbacks where the trusted party is assumed to be the caller and the untrusted code is the called code.
58
60
59
-
## \_Out\_writes\_
61
+
## `_Out_writes_`
60
62
61
63
The following example demonstrates a common misuse of `_Out_writes_`.
62
64
63
65
```cpp
66
+
#include<sal.h>
64
67
65
68
// Incorrect
66
69
voidFunc1(_Out_writes_(size) CHAR *pb,
67
70
DWORD size
68
71
);
69
72
```
70
73
71
-
The annotation `_Out_writes_` signifies that you have a buffer. It has `cb` bytes allocated, with the first byte initialized on exit. This annotation is not strictly wrong and it is helpful to express the allocated size. However, it does not tell how many elements are initialized by the function.
74
+
The annotation `_Out_writes_` signifies that you have a buffer. It has `cb` bytes allocated, with the first byte initialized on exit. This annotation isn't strictly wrong and it's helpful to express the allocated size. However, it doesn't tell how many elements are initialized by the function.
72
75
73
76
The next example shows three correct ways to fully specify the exact size of the initialized portion of the buffer.
The use of `_Out_ PSTR` is almost always wrong. This is interpreted as having an output parameter that points to a character buffer and it is NULL-terminated.
98
+
The use of `_Out_ PSTR` is almost always wrong. This combination is interpreted as having an output parameter that points to a character buffer and the buffer is null-terminated.
An annotation like `_In_ PCSTR` is common and useful. It points to an input string that has NULL termination because the precondition of `_In_` allows the recognition of a NULL-terminated string.
110
+
An annotation like `_In_ PCSTR` is common and useful. It points to an input string that has null termination because the precondition of `_In_` allows the recognition of a null-terminated string.
106
111
107
-
## \_In\_ WCHAR* p
112
+
## `_In_ WCHAR* p`
108
113
109
-
`_In_ WCHAR* p` says that there is an input pointer `p` that points to one character. However, in most cases, this is probably not the specification that is intended. Instead, what is probably intended is the specification of a NULL-terminated array; to do that, use `_In_ PWSTR`.
114
+
`_In_ WCHAR* p` says that there's an input pointer `p` that points to one character. However, in most cases, this is probably not the specification that is intended. Instead, what is probably intended is the specification of a null-terminated array; to do that, use `_In_ PWSTR`.
Missing the proper specification of NULL termination is common. Use the appropriate `STR` version to replace the type, as shown in the following example.
126
+
Missing the proper specification of null termination is common. Use the appropriate `STR` version to replace the type, as shown in the following example.
If the parameter is a pointer and you want to express the range of the value of the element that is pointed to by the pointer, use `_Deref_out_range_` instead of `_Out_range_`. In the following example, the range of *pcbFilled is expressed, not pcbFilled.
147
+
If the parameter is a pointer and you want to express the range of the value of the element that's pointed to by the pointer, use `_Deref_out_range_` instead of `_Out_range_`. In the following example, the range of *pcbFilled is expressed, not pcbFilled.
140
148
141
149
```cpp
150
+
#include <sal.h>
142
151
143
152
// Incorrect
144
153
void Func1(
@@ -155,13 +164,14 @@ void Func2(
155
164
);
156
165
```
157
166
158
-
`_Deref_out_range_(0, cbSize)`is not strictly required for some tools because it can be inferred from `_Out_writes_to_(cbSize,*pcbFilled)`, but it is shown here for completeness.
167
+
`_Deref_out_range_(0, cbSize)`isn't strictly required for some tools because it can be inferred from `_Out_writes_to_(cbSize,*pcbFilled)`, but it's shown here for completeness.
159
168
160
-
## Wrong context in \_When\_
169
+
## Wrong context in `_When_`
161
170
162
171
Another common mistake is to use post-state evaluation for preconditions. In the following example, `_Requires_lock_held_` is a precondition.
The expression `result` refers to a post-state value that is not available in pre-state.
185
+
The expression `return` refers to a post-state value that isn't available in pre-state.
176
186
177
-
## TRUE in \_Success\_
187
+
## `TRUE` in `_Success_`
178
188
179
-
If the function succeeds when the return value is nonzero, use `return != 0` as the success condition instead of `return == TRUE`. Nonzero does not necessarily mean equivalence to the actual value that the compiler provides for `TRUE`. The parameter to `_Success_` is an expression, and the following expressions are evaluated as equivalent: `return != 0`, `return != false`, `return != FALSE`, and `return` with no parameters or comparisons.
189
+
If the function succeeds when the return value is nonzero, use `return != 0` as the success condition instead of `return == TRUE`. Nonzero doesn't necessarily mean equivalence to the actual value that the compiler provides for `TRUE`. The parameter to `_Success_` is an expression, and the following expressions are evaluated as equivalent: `return != 0`, `return != false`, `return != FALSE`, and `return` with no parameters or comparisons.
For a reference variable, the previous version of SAL used the implied pointer as the annotation target and required the addition of a `__deref` to annotations that attached to a reference variable. This version uses the object itself and does not require the additional `_Deref_`.
207
+
For a reference variable, the previous version of SAL used the implied pointer as the annotation target and required the addition of a `__deref` to annotations that attached to a reference variable. This version uses the object itself and doesn't require the additional `_Deref_`.
198
208
199
209
```cpp
210
+
#include<sal.h>
200
211
201
212
// Incorrect
202
213
voidFunc1(
@@ -216,6 +227,7 @@ void Func2(
216
227
The following example shows a common problem in return value annotations.
In this example, `_Out_opt_` says that the pointer might be NULL as part of the precondition. However, preconditions cannot be applied to the return value. In this case, the correct annotation is `_Ret_maybenull_`.
239
+
In this example, `_Out_opt_` says that the pointer might be `NULL` as part of the precondition. However, preconditions can't be applied to the return value. In this case, the correct annotation is `_Ret_maybenull_`.
228
240
229
241
## See also
230
242
231
-
[Using SAL Annotations to Reduce C/C++ Code Defects](../code-quality/using-sal-annotations-to-reduce-c-cpp-code-defects.md)
The **`export`** keyword may not appear in a module implementation file. When **`export`** is applied to a namespace name, all names in the namespace are exported.
58
58
59
59
## import
60
60
61
-
Use an **import** declaration to make a module's names visible in your program. The import declaration must appear after the module declaration and after any #include directives, but before any declarations in the file.
61
+
Use an **`import`** declaration to make a module's names visible in your program. The `import` declaration must appear after the `module` declaration and after any `#include` directives, but before any declarations in the file.
62
62
63
63
```cpp
64
64
module ModuleA;
@@ -100,7 +100,7 @@ int i; module ;
100
100
101
101
**Microsoft Specific**
102
102
103
-
In Microsoft C++, the tokens **import** and **module** are always identifiers and never keywords when they are used as arguments to a macro.
103
+
In Microsoft C++, the tokens **`import`** and **`module`** are always identifiers and never keywords when they are used as arguments to a macro.
0 commit comments