SAL Annotations

If you examine the library header files, you will notice some unusual annotations such as _In_z and _Out_z_cap_(_Size). These are examples of Microsoft's standard source code annotation language (SAL), which provides a set of annotations to describe how a function uses its parameters—the assumptions it makes about them, and the guarantees it makes upon finishing. The header file <sal.h> defines the annotations.

Annotations may be placed before either a function parameter's type or its return type, and describe the function's behavior regarding the parameter or return value. There are two classes of annotations: buffer annotations and advanced annotations. Buffer annotations describe how functions use their pointer parameters, and advanced annotations either describe complex/unusual buffer behavior, or provide additional information about a parameter that is not otherwise expressible.

Buffer Annotations

The most important annotations provide a consistent way to annotate buffer parameters or return values for a function. Each of these annotations describes a single buffer (which could be a string, a fixed-length or variable-length array, or just a pointer) that the function interacts with—where it is, how large it is, how much is initialized, and what the function does with it.

The appropriate macro for a given buffer can be constructed using the tables below. Pick an appropriate value from the Layers table, and then add any appropriate options from the Options table. Some combinations of values do not make sense as buffer annotations. Only meaningful annotations can be added to your code; for a list of these, see the buffer annotation definitions section in <sal.h>.

Only a single buffer annotation should be used for each parameter.

Layers

Possible choices

Parameters Layer

(none)

_In_

_Out_

_Inout_

_Deref_out_

Return Value Layer

_Ret_

_Deref_ret_

Pre / Post Layer

(used only if no suitable option exists in the Parameters layer or Return Value layer)

_Pre_

_Post_

_Deref_pre_

_Deref_post_

Options

Possible choices

Optional

(none)

opt_

Null-termination

(none)

z_

Extent

(none)

cap_[c_|x_](size)

bytecap_[c_|x_](size)

count_[c_|x_](size)

bytecount_[c_|x_](size)

ptrdiff_cap_(ptr)

ptrdiff_count_(ptr)

The various categories and their respective choices are described below.

Parameters Layer

Describes how the function uses the buffer of a formal parameter.

(none)

The buffer is not accessed. The caller must provide the buffer. This should only be used for alloc and free functions.

_In_

The function will only read from the buffer. The caller must provide the buffer and initialize it.

_Out_

The function will only write to the buffer. The caller must provide the buffer, and the function will initialize it.

_Inout_

The function may freely read from and write to the buffer. The caller must provide the buffer and initialize it.

_Deref_out_

This option applies to output parameters that are dereferenced. Given a parameter p, *p is the buffer pointer. p must not be NULL.

The function will only write to the buffer. The function will provide the buffer and initialize it.

Return Value Layer

Describes how the function uses the buffer of a return value.

(none)

The buffer is not accessed. The function will provide the buffer, and it will be uninitialized at exit. This should only be used for alloc and free functions.

_Ret_

The function will provide the buffer and initialize it.

_Deref_ret_

This option applies to return values that are dereferenced. Given a return value p, *p is the buffer pointer. p must not be NULL.

The function will provide the buffer and initialize it.

Pre / Post Layer

Describes how the function uses the buffer. Only use the values in this layer if the values in the Parameters layer or Return Value layer do not apply.

_Pre_

Describes conditions that must be met before a function is called.

_Post_

Describes conditions that must apply after a function is called.

_Deref_pre_

Describes conditions for array elements of dereferenced pointer parameters that must be met before the call

_Deref_post_

Describes conditions that must apply after a function is called.

Optional Option

Describes if the buffer itself is optional. These annotations can be applied to values in the Parameters layer, Return Value layer, or Pre / Post layer.

(none)

The pointer to the buffer must not be NULL.

opt_

The pointer to the buffer might be NULL. It will be checked before being dereferenced.

Null-Termination Option

States if the presence of a '\0' marks the end of valid elements in the buffer. These annotations can be applied to values in the Parameters layer, Return Value layer, or Pre / Post layer.

(none)

The buffer may not be null-terminated and a '\0' does not indicate the end of the buffer.

z_

A '\0' indicates the end of the buffer.

Extent Option

These options apply to readable and writable buffers. These annotations can be applied to values in the Parameters layer, Return Value layer, or Pre / Post layer.

(none)

The parameter or return value is not a readable or writable buffer.

cap_[c_|x_](size)

bytecap_[c_|x_](size)

ptrdiff_cap_(ptr)

Describes the writable size of the buffer. This option is typically used with the _Out_ annotation.

If the size is given in elements, use cap_. If the size is given in bytes, use bytecap_. If the size is given by a limiting pointer, use ptrdiff_cap_.

If the buffer size is a non-constant parameter, you do not need to specify c_ or x_. For example, valid annotations include cap_(size) and bytecap_(size).

If the buffer size is a constant expression, specify the c_ option. For example, valid annotations include cap_c_(size) and bytecap_c_(size).

If the buffer size is neither a constant expression nor a parameter, specify the x_ option. For example, valid annotations include cap_x_(size) and bytecap_x_(size).

count_[c_|x_](size)

bytecount_[c_|x_](size)

ptrdiff_count_(ptr)

Describes the writable size of the buffer. This option is typically used with the _In_ annotation.

If the size is given in elements, use count_. If the size is given in bytes, use bytecount_. If the size is given by a limiting pointer, use ptrdiff_count_.

If the buffer size is a non-constant parameter, you do not need to specify c_ or x_. For example, valid annotations include count_(size) and bytecount_(size).

If the buffer size is a constant expression, specify the c_ option. For example, valid annotations include count_c_(size) and bytecount_c_(size).

If the buffer size is neither a constant expression nor a parameter, specify the x_ option. For example, valid annotations include count_x_(size) and bytecount_x_(size).

Advanced Annotations

Advanced annotations describe behavior that is not expressible with the regular buffer macros. These may be used either to annotate buffer parameters that involve complex or conditional behavior, or to enrich existing annotations with additional information.

Annotation

Description

_Check_return_

Return value must not be ignored by callers of this function.

_Printf_format_string_

A string that contains % markers in the style of printf.

_Scanf_format_string_

A string that contains % markers in the style of scanf.

_Scanf_s_format_string_

A string that contains % markers in the style of scanf_s.

_Success_(expr)

expr indicates whether the function succeeded or not. If expr is true at exit, all the function's guarantees (as given by other annotations) must hold. If expr is false at exit, the caller should not expect any of the function's guarantees to hold. If not used, the function must always satisfy its guarantees. Added automatically to functions that indicate success in standard ways, such as by returning an HRESULT.

See Also

Concepts

C Run-Time Libraries