Skip to content

Commit 529ab1b

Browse files
author
Colin Robertson
committed
Fix feedback issues
1 parent 6f03c1f commit 529ab1b

7 files changed

Lines changed: 114 additions & 92 deletions

File tree

docs/c-runtime-library/secure-template-overloads.md

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,72 +40,76 @@ translation.priority.ht:
4040
- "zh-tw"
4141
---
4242
# Secure Template Overloads
43-
Many CRT functions have been deprecated in favor of newer, security-enhanced versions (for example, `strcpy_s` is the more secure replacement for `strcpy`). The CRT provides template overloads to help ease the transition to the more secure variants.
43+
Microsoft has deprecated many C Runtime library (CRT) functions in favor of security-enhanced versions. For example, `strcpy_s` is the more secure replacement for `strcpy`. The deprecated functions are common sources of security bugs, because they do not prevent operations that can overwrite memory. By default, the compiler produces a deprecation warning when you use one of these functions. The CRT provides C++ template overloads for these functions to help ease the transition to the more secure variants.
4444

45-
For example, this code generates a warning because `strcpy` is deprecated:
45+
For example, this code snippet generates a warning because `strcpy` is deprecated:
4646

47-
`char szBuf[10];`
47+
```cpp
48+
char szBuf[10];
49+
strcpy(szBuf, "test"); // warning: deprecated
50+
```
4851
49-
`strcpy(szBuf, "test"); // warning: deprecated`
52+
The deprecation warning is there to tell you that your code may be unsafe. If you have verified that your code can't overwrite memory, you have several choices. You can choose to ignore the warning, you can define the symbol `_CRT_SECURE_NO_WARNINGS` before the include statements for the CRT headers to suppress the warning, or you can update your code to use `strcpy_s`:
5053
51-
You can ignore the warning. Define the symbol `_CRT_SECURE_NO_WARNINGS` to suppress the warning, or update the code to use `strcpy_s`:
54+
```cpp
55+
char szBuf[10];
56+
strcpy_s(szBuf, 10, "test"); // security-enhanced _s function
57+
```
5258

53-
`char szBuf[10];`
59+
The template overloads provide additional choices. If you define `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` to 1, this enables template overloads of standard CRT functions that call the more secure variants automatically. If `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` is 1, then no changes to your code are necessary. Behind the scenes, the call to `strcpy` is changed to a call to `strcpy_s` with the size argument supplied automatically.
5460

55-
`strcpy_s(szBuf, 10, "test"); // security-enhanced _s function`
61+
```cpp
62+
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
5663

57-
The template overloads provide additional choices. Defining `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` to 1 enables template overloads of standard CRT functions that call the more secure variants automatically. If `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` is 1, then no changes to the code are necessary. Behind the scenes, the call to `strcpy` will be changed to a call to `strcpy_s` with the size argument supplied automatically.
64+
// ...
5865

59-
`#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1`
66+
char szBuf[10];
67+
strcpy(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")
68+
```
6069
61-
`...`
62-
63-
`char szBuf[10];`
64-
65-
`strcpy(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")`
66-
67-
`_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` does not affect the functions that take a count, such as `strncpy`. To enable template overloads for the count functions, define `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT` to 1. Before doing so, however, make sure that your code passes the count of characters, not the size of the buffer (a common mistake). Also, code that explicitly writes a null terminator at the end of the buffer after the function call is unnecessary if the secure variant is called. If you need truncation behavior, see [_TRUNCATE](../c-runtime-library/truncate.md).
70+
The macro `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` does not affect the functions that take a count, such as `strncpy`. To enable template overloads for the count functions, define `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT` to 1. Before doing so, however, make sure that your code passes the count of characters, not the size of the buffer (a common mistake). Also, code that explicitly writes a null terminator at the end of the buffer after the function call is unnecessary if the secure variant is called. If you need truncation behavior, see [_TRUNCATE](../c-runtime-library/truncate.md).
6871
6972
> [!NOTE]
7073
> The macro `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT` requires that `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` is also defined as 1. If `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT` is defined as 1 and `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` is defined as 0, the application will not perform any template overloads.
7174
72-
Defining `_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES` to 1 enables template overloads of the secure variants (names ending in "_s"). In this case, if `_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES` is 1, then one small change must be made to the original code:
73-
74-
`#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1`
75+
When you define `_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES` to 1, it enables template overloads of the secure variants (names ending in "_s"). In this case, if `_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES` is 1, then one small change must be made to the original code:
7576
76-
`...`
77+
```cpp
78+
#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
7779
78-
`char szBuf[10];`
80+
// ...
7981
80-
`strcpy_s(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")`
82+
char szBuf[10];
83+
strcpy_s(szBuf, "test"); // ==> strcpy_s(szBuf, 10, "test")
84+
```
8185

82-
Only the name of the function needs to be changed (by adding "_s"); the template overload will take care of providing the size argument.
86+
Only the name of the function needs to be changed (by adding "_s"); the template overload takes care of providing the size argument.
8387

8488
By default, `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES` and `_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT` are defined as 0 (disabled) and `_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES` is defined as 1 (enabled).
8589

8690
Note that these template overloads only work for static arrays. Dynamically allocated buffers require additional source code changes. Revisiting the above examples:
8791

88-
`#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1`
92+
```cpp
93+
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
8994

90-
`...`
95+
// ...
9196

92-
`char *szBuf = (char*)malloc(10);`
93-
94-
`strcpy(szBuf, "test"); // still deprecated; have to change to`
95-
96-
`// strcpy_s(szBuf, 10, "test");`
97+
char *szBuf = (char*)malloc(10);
98+
strcpy(szBuf, "test"); // still deprecated; you have to change it to
99+
// strcpy_s(szBuf, 10, "test");
100+
```
97101
98102
And this:
99103
100-
`#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1`
101-
102-
`...`
103-
104-
`char *szBuf = (char*)malloc(10);`
104+
```cpp
105+
#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
105106
106-
`strcpy_s(szBuf, "test"); // doesn't compile; have to change to`
107+
// ...
107108
108-
`// strcpy_s(szBuf, 10, "test");`
109+
char *szBuf = (char*)malloc(10);
110+
strcpy_s(szBuf, "test"); // doesn't compile; you have to change it to
111+
// strcpy_s(szBuf, 10, "test");
112+
```
109113

110114
## See Also
111115
[Security Features in the CRT](../c-runtime-library/security-features-in-the-crt.md)

docs/cpp/exception-specifications-throw-cpp.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,29 +37,29 @@ translation.priority.ht:
3737
- "zh-tw"
3838
---
3939
# Exception Specifications (throw, noexcept) (C++)
40-
Exception specifications are a C++ language feature that indicate the programmer's intent about the exception types that can be propagated by a function. You can specify that a function may not exit by an exception by using an *exception specification*. The compiler can use this information to optimize calls to the function, and to terminate the program if an exception escapes the function. There are two kinds of exception specification. The *noexcept specification* is new in C++11. It specifies whether the set of potential exceptions that can escape the function is empty. The *dynamic exception specification*, or `throw(optional_type_list)` specification, is deprecated in C++11 and is only partially supported by Visual Studio. This exception specification was designed to provide summary information about what exceptions can be thrown out of a function, but in practice it was found to be problematic. The one dynamic exception specification that did prove to be somewhat useful was the unconditional `throw()` specification. For example, the function declaration:
40+
Exception specifications are a C++ language feature that indicate the programmer's intent about the exception types that can be propagated by a function. You can specify that a function may or may not exit by an exception by using an *exception specification*. The compiler can use this information to optimize calls to the function, and to terminate the program if an unexpected exception escapes the function. There are two kinds of exception specification. The *noexcept specification* is new in C++11. It specifies whether the set of potential exceptions that can escape the function is empty. The *dynamic exception specification*, or `throw(optional_type_list)` specification, is deprecated in C++11 and is only partially supported by Visual Studio. This exception specification was designed to provide summary information about what exceptions can be thrown out of a function, but in practice it was found to be problematic. The one dynamic exception specification that did prove to be somewhat useful was the unconditional `throw()` specification. For example, the function declaration:
4141

4242
```cpp
4343
void MyFunction(int i) throw();
4444
```
4545
4646
tells the compiler that the function does not throw any exceptions. It is the equivalent to using [__declspec(nothrow)](../cpp/nothrow-cpp.md). Its use is considered optional.
4747
48-
In the ISO C++11 Standard, [noexcept](../cpp/noexcept-cpp.md) operator was introduced and is supported in Visual Studio 2015 and later. Whenever possible, use `noexcept` to specify whether a function might throw exceptions. For example, use this function declaration instead of the one above:
48+
In the ISO C++11 Standard, the [noexcept](../cpp/noexcept-cpp.md) operator was introduced as a replacement. It is supported in Visual Studio 2015 and later. Whenever possible, use a `noexcept` expression to specify whether a function might throw exceptions. For example, use this function declaration instead of the one above:
4949
5050
```cpp
5151
void MyFunction(int i) noexcept;
5252
```
5353

54-
Visual C++ departs from the ISO C++ Standard in its implementation of dynamic exception specifications. The following table summarizes the Visual C++ implementation of exception specifications:
54+
While Visual C++ fully supports the `noexcept` expression, it departs from the ISO C++ Standard in its implementation of dynamic exception specifications. The following table summarizes the Visual C++ implementation of exception specifications:
5555

5656
|Exception specification|Meaning|
5757
|-----------------------------|-------------|
5858
|`noexcept`<br/>`noexcept(true)`<br/>`throw()`|The function does not throw an exception. However, if an exception is thrown out of a function marked `throw()`, the Visual C++ compiler calls `std::terminate`, not `std::unexpected`. See [std::unexpected](../c-runtime-library/reference/unexpected-crt.md) for more information. If a function is marked `noexcept`, `noexcept(true)`, or `throw()`, the Visual C++ compiler assumes that the function does not throw C++ exceptions and generates code accordingly. Because code optimizations might be performed by the C++ compiler based on the assumption that the function does not throw any C++ exceptions, if a function does throw an exception, the program may not execute correctly.|
59-
|`nothrow(false)`<br/>`throw(...)`<br/>No specification|The function can throw an exception of any type.|
60-
|`throw(type)`|The function can throw an exception of type `type`. In Visual C++, this syntax is accepted, but it is interpreted as `throw(...)`.|
59+
|`noexcept(false)`<br/>`throw(...)`<br/>No specification|The function can throw an exception of any type.|
60+
|`throw(type)`|The function can throw an exception of type `type`. In Visual C++, this syntax is accepted, but it is interpreted as `noexcept(false)`.|
6161

62-
If exception handling is used in an application, there must be a function in the call stack that handles thrown exceptions before they exit a function marked `noexcept`, `noexcept(true)`, or `throw()`. If any functions called between the one that throws an exception and the one that handles the exception are specified as `noexcept`, `noexcept(true)`, or `throw()`, the program is terminated when the noexcept function propagates the exception.
62+
If exception handling is used in an application, there must be a function in the call stack that handles thrown exceptions before they exit the outer scope of a function marked `noexcept`, `noexcept(true)`, or `throw()`. If any functions called between the one that throws an exception and the one that handles the exception are specified as `noexcept`, `noexcept(true)`, or `throw()`, the program is terminated when the noexcept function propagates the exception.
6363

6464
The exception behavior of a function depends on the following factors:
6565

@@ -76,8 +76,8 @@ void MyFunction(int i) noexcept;
7676
|Function|/EHsc|/EHs|/EHa|/EHac|
7777
|--------------|------------|-----------|-----------|------------|
7878
|C++ function with no exception specification|Yes|Yes|Yes|Yes|
79-
|C++ function with `nothrow`, `nothrow(true)`, or `throw()` exception specification|No|No|Yes|Yes|
80-
|C++ function with `nothrow(false)`, `throw(...)`, or `throw(type)` exception specification|Yes|Yes|Yes|Yes|
79+
|C++ function with `noexcept`, `noexcept(true)`, or `throw()` exception specification|No|No|Yes|Yes|
80+
|C++ function with `noexcept(false)`, `throw(...)`, or `throw(type)` exception specification|Yes|Yes|Yes|Yes|
8181

8282
## Example
8383

docs/cpp/noexcept-cpp.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,30 +37,32 @@ translation.priority.ht:
3737

3838
## Syntax
3939

40-
> **noexcept**
41-
> **noexcept(** *constant_expression* **)**
40+
> *noexcept-expression*:
41+
> &nbsp;&nbsp;&nbsp;&nbsp;**noexcept**
42+
> &nbsp;&nbsp;&nbsp;&nbsp;**noexcept(** *constant-expression* **)**
4243
4344
### Parameters
44-
*constant_expression*
45+
*constant-expression*
4546
A constant expression of type `bool` that represents whether the set of potential exception types is empty. The unconditional version is equivalent to `noexcept(true)`.
4647

4748
## Remarks
48-
Unary conditional operator `noexcept(true)` and its unconditional synonym `noexcept` specify that the function never throws an exception and never allows an exception to be propagated from any other function that it invokes either directly or indirectly. More specifically, a function is `noexcept` only if all the functions that it calls are also `noexcept` or `const`, and there are no potentially evaluated dynamic casts that require a run-time check, typeid expressions applied to a glvalue expression whose type is a polymorphic class type, or `throw` expressions. However, the compiler does not necessarily check every code path for exceptions that might bubble up to a `noexcept` function. If an exception does reach a function marked `noexcept`, [std::terminate](../standard-library/exception-functions.md#terminate) is invoked immediately, and there is no guarantee that destructors of any in-scope objects will be invoked.
49+
A *noexcept expression* is a kind of *exception specification*, a suffix to a function declaration that represents a set of types that might be matched by an exception handler for any exception that exits a function. Unary conditional operator `noexcept(`*constant_expression*`)` where *constant_expression* yeilds `true`, and its unconditional synonym `noexcept`, specify that the set of potential exception types that can exit a function is empty. That is, the function never throws an exception and never allows an exception to be propagated outside its scope. The operator `noexcept(`*constant_expression*`)` where *constant_expression* yeilds `false`, or the absence of an exception specification (other than for a destructor or deallocation function), indicates that the set of potential exceptions that can exit the function is the set of all types.
50+
51+
Mark a function as `noexcept` only if all the functions that it calls, either directly or indirectly, are also `noexcept` or `const`. The compiler does not necessarily check every code path for exceptions that might bubble up to a `noexcept` function. If an exception does exit the outer scope of a function marked `noexcept`, [std::terminate](../standard-library/exception-functions.md#terminate) is invoked immediately, and there is no guarantee that destructors of any in-scope objects will be invoked. Use `noexcept` instead of the dynamic exception specifier `throw`, which is deprecated in C++11 and later and not fully implemented in Visual Studio. We recommended you apply `noexcept` to any function that never allows an exception to propagate up the call stack. When a function is declared `noexcept`, it enables the compiler to generate more efficient code in several different contexts.
4952

50-
A function declared by using a conditional `noexcept` expression that evaluates to `false` (or a function that has no `noexcept` expression, other than a destructor or deallocation function) specifies that it does permit exceptions of all types to propagate. For example, a template function that copies its argument might be declared `noexcept` on the condition that the object being copied is a plain old data type (POD). Such a function could be declared like this:
53+
## Example
54+
A template function that copies its argument might be declared `noexcept` on the condition that the object being copied is a plain old data type (POD). Such a function could be declared like this:
5155

5256
```cpp
5357
#include <type_traits>
5458

5559
template <typename T>
56-
T copy_object(T& obj) noexcept(std::is_pod<T>)
60+
T copy_object(const T& obj) noexcept(std::is_pod<T>)
5761
{
5862
// ...
5963
}
6064
```
6165
62-
Use `noexcept` instead of the dynamic exception specifier `throw`, which is deprecated in C++11 and later. We recommended you apply `noexcept` to any function that never allows an exception to propagate up the call stack. A function that is declared `noexcept` enables compilers to generate more efficient code in several different contexts.
63-
6466
## See Also
6567
[C++ Exception Handling](../cpp/cpp-exception-handling.md)
6668
[Exception Specifications (throw, noexcept)](../cpp/exception-specifications-throw.md)

0 commit comments

Comments
 (0)