Annotating Function Parameters and Return Values

Note

This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here

This article describes typical uses of annotations for simple function parameters—scalars, and pointers to structures and classes—and most kinds of buffers. This article also shows common usage patterns for annotations. For additional annotations that are related to functions, see Annotating Function Behavior

Pointer Parameters

For the annotations in the following table, when a pointer parameter is being annotated, the analyzer reports an error if the pointer is null. This applies to pointers and to any data item that's pointed to.

Annotations and Descriptions

  • _In_

    Annotates input parameters that are scalars, structures, pointers to structures and the like. Explicitly may be used on simple scalars. The parameter must be valid in pre-state and will not be modified.

  • _Out_

    Annotates output parameters that are scalars, structures, pointers to structures and the like. Do not apply this to an object that cannot return a value—for example, a scalar that's passed by value. The parameter does not have to be valid in pre-state but must be valid in post-state.

  • _Inout_

    Annotates a parameter that will be changed by the function. It must be valid in both pre-state and post-state, but is assumed to have different values before and after the call. Must apply to a modifiable value.

  • _In_z_

    A pointer to a null-terminated string that's used as input. The string must be valid in pre-state. Variants of PSTR, which already have the correct annotations, are preferred.

  • _Inout_z_

    A pointer to a null-terminated character array that will be modified. It must be valid before and after the call, but the value is assumed to have changed. The null terminator may be moved, but only the elements up to the original null terminator may be accessed.

  • _In_reads_(s)

    _In_reads_bytes_(s)

    A pointer to an array, which is read by the function. The array is of size s elements, all of which must be valid.

    The _bytes_ variant gives the size in bytes instead of elements. Use this only when the size cannot be expressed as elements. For example, char strings would use the _bytes_ variant only if a similar function that uses wchar_t would.

  • _In_reads_z_(s)

    A pointer to an array that is null-terminated and has a known size. The elements up to the null terminator—or s if there is no null terminator—must be valid in pre-state. If the size is known in bytes, scale s by the element size.

  • _In_reads_or_z_(s)

    A pointer to an array that is null-terminated or has a known size, or both. The elements up to the null terminator—or s if there is no null terminator—must be valid in pre-state. If the size is known in bytes, scale s by the element size. (Used for the strn family.)

  • _Out_writes_(s)

    _Out_writes_bytes_(s)

    A pointer to an array of s elements (resp. bytes) that will be written by the function. The array elements do not have to be valid in pre-state, and the number of elements that are valid in post-state is unspecified. If there are annotations on the parameter type, they are applied in post-state. For example, consider the following code.

    typedef _Null_terminated_ wchar_t *PWSTR; void MyStringCopy(_Out_writes_ (size) PWSTR p1, _In_ size_t size, _In_ PWSTR p2);

    In this example, the caller provides a buffer of size elements for p1. MyStringCopy makes some of those elements valid. More importantly, the _Null_terminated_ annotation on PWSTR means that p1 is null-terminated in post-state. In this way, the number of valid elements is still well-defined, but a specific element count is not required.

    The _bytes_ variant gives the size in bytes instead of elements. Use this only when the size cannot be expressed as elements. For example, char strings would use the _bytes_ variant only if a similar function that uses wchar_t would.

  • _Out_writes_z_(s)

    A pointer to an array of s elements. The elements do not have to be valid in pre-state. In post-state, the elements up through the null terminator—which must be present—must be valid. If the size is known in bytes, scale s by the element size.

  • _Inout_updates_(s)

    _Inout_updates_bytes_(s)

    A pointer to an array, which is both read and written to in the function. It is of size s elements, and valid in pre-state and post-state.

    The _bytes_ variant gives the size in bytes instead of elements. Use this only when the size cannot be expressed as elements. For example, char strings would use the _bytes_ variant only if a similar function that uses wchar_t would.

  • _Inout_updates_z_(s)

    A pointer to an array that is null-terminated and has a known size. The elements up through the null terminator—which must be present—must be valid in both pre-state and post-state. The value in the post-state is presumed to be different from the value in the pre-state; this includes the location of the null terminator. If the size is known in bytes, scale s by the element size.

  • _Out_writes_to_(s,c)

    _Out_writes_bytes_to_(s,c)

    _Out_writes_all_(s)

    _Out_writes_bytes_all_(s)

    A pointer to an array of s elements. The elements do not have to be valid in pre-state. In post-state, the elements up to the c-th element must be valid. If the size is known in bytes, scale s and c by the element size or use the _bytes_ variant, which is defined as:

    _Out_writes_to_(_Old_(s), _Old_(s)) _Out_writes_bytes_to_(_Old_(s), _Old_(s))

    In other words, every element that exists in the buffer up to s in the pre-state is valid in the post-state. For example:

    void *memcpy(_Out_writes_bytes_all_(s) char *p1, _In_reads_bytes_(s) char *p2, _In_ int s); void * wordcpy(_Out_writes_all_(s) DWORD *p1, _In_reads_(s) DWORD *p2, _In_ int s);

  • _Inout_updates_to_(s,c)

    _Inout_updates_bytes_to_(s,c)

    A pointer to an array, which is both read and written by the function. It is of size s elements, all of which must be valid in pre-state, and c elements must be valid in post-state.

    The _bytes_ variant gives the size in bytes instead of elements. Use this only when the size cannot be expressed as elements. For example, char strings would use the _bytes_ variant only if a similar function that uses wchar_t would.

  • _Inout_updates_z_(s)

    A pointer to an array that is null-terminated and has a known size. The elements up through the null terminator—which must be present—must be valid in both pre-state and post-state. The value in the post-state is presumed to be different from the value in the pre-state; this includes the location of the null terminator. If the size is known in bytes, scale s by the element size.

  • _Out_writes_to_(s,c)

    _Out_writes_bytes_to_(s,c)

    _Out_writes_all_(s)

    _Out_writes_bytes_all_(s)

    A pointer to an array of s elements. The elements do not have to be valid in pre-state. In post-state, the elements up to the c-th element must be valid. If the size is known in bytes, scale s and c by the element size or use the _bytes_ variant, which is defined as:

    _Out_writes_to_(_Old_(s), _Old_(s)) _Out_writes_bytes_to_(_Old_(s), _Old_(s))

    In other words, every element that exists in the buffer up to s in the pre-state is valid in the post-state. For example:

    void *memcpy(_Out_writes_bytes_all_(s) char *p1, _In_reads_bytes_(s) char *p2, _In_ int s); void * wordcpy(_Out_writes_all_(s) DWORD *p1, _In_reads_(s) DWORD *p2, _In_ int s);

  • _Inout_updates_to_(s,c)

    _Inout_updates_bytes_to_(s,c)

    A pointer to an array, which is both read and written by the function. It is of size s elements, all of which must be valid in pre-state, and c elements must be valid in post-state.

    The _bytes_ variant gives the size in bytes instead of elements. Use this only when the size cannot be expressed as elements. For example, char strings would use the _bytes_ variant only if a similar function that uses wchar_t would.

  • _Inout_updates_all_(s)

    _Inout_updates_bytes_all_(s)

    A pointer to an array, which is both read and written by the function of size s elements. Defined as equivalent to:

    _Inout_updates_to_(_Old_(s), _Old_(s)) _Inout_updates_bytes_to_(_Old_(s), _Old_(s))

    In other words, every element that exists in the buffer up to s in the pre-state is valid in the pre-state and post-state.

    The _bytes_ variant gives the size in bytes instead of elements. Use this only when the size cannot be expressed as elements. For example, char strings would use the _bytes_ variant only if a similar function that uses wchar_t would.

  • _In_reads_to_ptr_(p)

    A pointer to an array for which the expression p_Curr_ (that is, p minus _Curr_) is defined by the appropriate language standard. The elements prior to p must be valid in pre-state.

  • _In_reads_to_ptr_z_(p)

    A pointer to a null-terminated array for which the expression p_Curr_ (that is, p minus _Curr_) is defined by the appropriate language standard. The elements prior to p must be valid in pre-state.

  • _Out_writes_to_ptr_(p)

    A pointer to an array for which the expression p_Curr_ (that is, p minus _Curr_) is defined by the appropriate language standard. The elements prior to p do not have to be valid in pre-state and must be valid in post-state.

  • _Out_writes_to_ptr_z_(p)

    A pointer to a null-terminated array for which the expression p_Curr_ (that is, p minus _Curr_) is defined by the appropriate language standard. The elements prior to p do not have to be valid in pre-state and must be valid in post-state.

Optional Pointer Parameters

When a pointer parameter annotation includes _opt_, it indicates that the parameter may be null. Otherwise, the annotation performs the same as the version that doesn't include _opt_. Here is a list of the _opt_ variants of the pointer parameter annotations:

_In_opt_, _Out_opt_, _Inout_opt_, _In_opt_z_, _Inout_opt_z_, _In_reads_opt_, _In_reads_bytes_opt_, _In_reads_opt_z_|_Out_writes_opt_, _Out_writes_opt_z_, _Inout_updates_opt_, _Inout_updates_bytes_opt_, _Inout_updates_opt_z_, _Out_writes_to_opt_, _Out_writes_bytes_to_opt_, _Out_writes_all_opt_, _Out_writes_bytes_all_opt_|_Inout_updates_to_opt_, _Inout_updates_bytes_to_opt_, _Inout_updates_all_opt_, _Inout_updates_bytes_all_opt_, _In_reads_to_ptr_opt_, _In_reads_to_ptr_opt_z_, _Out_writes_to_ptr_opt_, _Out_writes_to_ptr_opt_z_|

Output Pointer Parameters

Output pointer parameters require special notation to disambiguate null-ness on the parameter and the pointed-to location.

Annotations and Descriptions

  • _Outptr_

    Parameter cannot be null, and in the post-state the pointed-to location cannot be null and must be valid.

  • _Outptr_opt_

    Parameter may be null, but in the post-state the pointed-to location cannot be null and must be valid.

  • _Outptr_result_maybenull_

    Parameter cannot be null, and in the post-state the pointed-to location can be null.

  • _Outptr_opt_result_maybenull_

    Parameter may be null, and in the post-state the pointed-to location can be null.

    In the following table, additional substrings are inserted into the annotation name to further qualify the meaning of the annotation. The various substrings are _z, _COM_, _buffer_, _bytebuffer_, and _to_.

Important

If the interface that you are annotating is COM, use the COM form of these annotations. Do not use the COM annotations with any other type interface.

Annotations and Descriptions

  • _Outptr_result_z_

    _Outptr_opt_result_z_

    _Outptr_result_maybenull_z_

    _Ouptr_opt_result_maybenull_z_

    The returned pointer has the _Null_terminated_ annotation.

  • _COM_Outptr_

    _COM_Outptr_opt_

    _COM_Outptr_result_maybenull_

    _COM_Outptr_opt_result_maybenull_

    The returned pointer has COM semantics, and therefore carries an _On_failure_ post-condition that the returned pointer is null.

  • _Outptr_result_buffer_(s)

    _Outptr_result_bytebuffer_(s)

    _Outptr_opt_result_buffer_(s)

    _Outptr_opt_result_bytebuffer_(s)

    The returned pointer points to a valid buffer of size s elements or bytes.

  • _Outptr_result_buffer_to_(s, c)

    _Outptr_result_bytebuffer_to_(s, c)

    _Outptr_opt_result_buffer_to_(s,c)

    _Outptr_opt_result_bytebuffer_to_(s,c)

    The returned pointer points to a buffer of size s elements or bytes, of which the first c are valid.

    Certain interface conventions presume that output parameters are nullified on failure. Except for explicitly COM code, the forms in the following table are preferred. For COM code, use the corresponding COM forms that are listed in the previous section.

    Annotations and Descriptions

  • _Result_nullonfailure_

    Modifies other annotations. The result is set to null if the function fails.

  • _Result_zeroonfailure_

    Modifies other annotations. The result is set to zero if the function fails.

  • _Outptr_result_nullonfailure_

    The returned pointer points to a valid buffer if the function succeeds, or null if the function fails. This annotation is for a non-optional parameter.

  • _Outptr_opt_result_nullonfailure_

    The returned pointer points to a valid buffer if the function succeeds, or null if the function fails. This annotation is for an optional parameter.

  • _Outref_result_nullonfailure_

    The returned pointer points to a valid buffer if the function succeeds, or null if the function fails. This annotation is for a reference parameter.

Output Reference Parameters

A common use of the reference parameter is for output parameters. For simple output reference parameters—for example, int&_Out_ provides the correct semantics. However, when the output value is a pointer—for example int *&—the equivalent pointer annotations like _Outptr_ int ** don’t provide the correct semantics. To concisely express the semantics of output reference parameters for pointer types, use these composite annotations:

Annotations and Descriptions

  • _Outref_

    Result must be valid in post-state and cannot be null.

  • _Outref_result_maybenull_

    Result must be valid in post-state, but may be null in post-state.

  • _Outref_result_buffer_(s)

    Result must be valid in post-state and cannot be null. Points to valid buffer of size s elements.

  • _Outref_result_bytebuffer_(s)

    Result must be valid in post-state and cannot be null. Points to valid buffer of size s bytes.

  • _Outref_result_buffer_to_(s, c)

    Result must be valid in post-state and cannot be null. Points to buffer of s elements, of which the first c are valid.

  • _Outref_result_bytebuffer_to_(s, c)

    Result must be valid in post-state and cannot be null. Points to buffer of s bytes of which the first c are valid.

  • _Outref_result_buffer_all_(s)

    Result must be valid in post-state and cannot be null. Points to valid buffer of size s valid elements.

  • _Outref_result_bytebuffer_all_(s)

    Result must be valid in post-state and cannot be null. Points to valid buffer of s bytes of valid elements.

  • _Outref_result_buffer_maybenull_(s)

    Result must be valid in post-state, but may be null in post-state. Points to valid buffer of size s elements.

  • _Outref_result_bytebuffer_maybenull_(s)

    Result must be valid in post-state, but may be null in post-state. Points to valid buffer of size s bytes.

  • _Outref_result_buffer_to_maybenull_(s, c)

    Result must be valid in post-state, but may be null in post-state. Points to buffer of s elements, of which the first c are valid.

  • _Outref_result_bytebuffer_to_maybenull_(s,c)

    Result must be valid in post-state, but may be null in post state. Points to buffer of s bytes of which the first c are valid.

  • _Outref_result_buffer_all_maybenull_(s)

    Result must be valid in post-state, but may be null in post state. Points to valid buffer of size s valid elements.

  • _Outref_result_bytebuffer_all_maybenull_(s)

    Result must be valid in post-state, but may be null in post state. Points to valid buffer of s bytes of valid elements.

Return Values

The return value of a function resembles an _Out_ parameter but is at a different level of de-reference, and you don't have to consider the concept of the pointer to the result. For the following annotations, the return value is the annotated object—a scalar, a pointer to a struct, or a pointer to a buffer. These annotations have the same semantics as the corresponding _Out_ annotation.

_Ret_z_, _Ret_writes_(s), _Ret_writes_bytes_(s), _Ret_writes_z_(s), _Ret_writes_to_(s,c), _Ret_writes_maybenull_(s), _Ret_writes_to_maybenull_(s), _Ret_writes_maybenull_z_(s)|_Ret_maybenull_, _Ret_maybenull_z_, _Ret_null_, _Ret_notnull_, _Ret_writes_bytes_to_, _Ret_writes_bytes_maybenull_, _Ret_writes_bytes_to_maybenull_

Other Common Annotations

Annotations and Descriptions

  • _In_range_(low, hi)

    _Out_range_(low, hi)

    _Ret_range_(low, hi)

    _Deref_in_range_(low, hi)

    _Deref_out_range_(low, hi)

    _Deref_inout_range_(low, hi)

    _Field_range_(low, hi)

    The parameter, field, or result is in the range (inclusive) from low to hi. Equivalent to _Satisfies_(_Curr_ >= low && _Curr_ <= hi) that is applied to the annotated object together with the appropriate pre-state or post-state conditions.

    Important

    Although the names contain "in" and "out", the semantics of _In_ and _Out_ do not apply to these annotations.

  • _Pre_equal_to_(expr)

    _Post_equal_to_(expr)

    The annotated value is exactly expr. Equivalent to _Satisfies_(_Curr_ == expr) that is applied to the annotated object together with the appropriate pre-state or post-state conditions.

  • _Struct_size_bytes_(size)

    Applies to a struct or class declaration. Indicates that a valid object of that type may be larger than the declared type, with the number of bytes being given by size. For example:

    typedef _Struct_size_bytes_(nSize) struct MyStruct { size_t nSize; ... };

    The buffer size in bytes of a parameter pM of type MyStruct * is then taken to be:

    min(pM->nSize, sizeof(MyStruct))

Code Analysis Team Blog

See Also

Using SAL Annotations to Reduce C/C++ Code Defects
Understanding SAL
Annotating Function Behavior
Annotating Structs and Classes
Annotating Locking Behavior
Specifying When and Where an Annotation Applies
Intrinsic Functions
Best Practices and Examples