对函数参数和返回值进行批注

本文描述了简单函数参数的标量注释的典型用途和结构指针。和类以及大多数缓冲区。本文还显示注释的常见使用模式。有关相关函数的其他说明,请参见 对函数行为进行批注

指针参数

对于下表的注释,当指针参数进行批注时,如果指针为空则分析程序所报告错误。这适用于指针和它指向的所有数据项。

批注

说明

_In_

批注是标量,结构,指向结构的指针、的输入参数。在简单 (标量可以显式使用。参数一定适用于前状态,并且将不会进行修改。

_Out_

批注是标量,结构,指向结构的指针和类似的输出参数。禁止把它应用于不能返回值的对象——例如,通过值标量。参数不必须在之前的状态是有效的状态,但在之后的状态必须是有效的。

_Inout_

标注函数将更改的参数。在调用之前和之后它必须是有效的,但假定在之前和之后具有不同的值。必须适用于可修改的值。

_In_z_

以 null 结尾的字符串的指针为输入。字符串一定适用于前状态。已具有正确的注释的PSTR变量是首选方法。

_Inout_z_

将修改的 null 终止的字符数组的指针。在调用之前和之后都必须有效,但是假定值已经更改。空的终结器可以移动,但只有原始的空终结器元素可以访问。

_In_reads_(s)

_In_reads_bytes_(s)

一个数组的指针,可被该函数读取。数组大小是 s 元素,该元素绑定有效。

_bytes_ 变量以字节为范围而不是元素。当范围不能表示为元素时,请使用此方法。例如,char 字符串将使用 _bytes_ 变量仅当一个相似的函数使用 wchar_t 时会。

_In_reads_z_(s)

指向以 null 终止并具有已知大小的数组的指针。空的终结器或 s 的元素,如果没有 Null 结束符的前面必须是有效状态。如果范围以字节为单位,通过元素范围缩放 s。

_In_reads_or_z_(s)

指向以 null 终止或具有已知大小的数组或二者都有的指针。空的终结器或 s 的元素,如果没有 Null 结束符的前面必须是有效状态。如果范围以字节为单位,通过元素范围缩放 s。(用于 strn 族。)

_Out_writes_(s)

_Out_writes_bytes_(s)

该函数将写入指向数组s的指针元素。数组元素在调用之前不必是有效的,而且,调用之后有效的元素数目是不可确定的。如果参数类型含有批注,则它们被应用在发送状态之后。例如,考虑下面的代码。

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

在本例中,调用方为 p1提供缓冲区 size 元素。MyStringCopy 使某些元素有效。更重要的是,PWSTR 上的注释 _Null_terminated_ 意味着 p1 在发送 null 终止状态。这样一来,有效元素的数量是显式定义,但不需要特定的元素数。

_bytes_ 变量以字节为范围而不是元素。当范围不能表示为元素时,请使用此方法。例如,char 字符串将使用 _bytes_ 变量仅当一个相似的函数使用 wchar_t 时会。

_Out_writes_z_(s)

指向 s 元素的数组的指针。元素不必是有效的在调用以前的状态。在发送状态后,元素引发通过终结器必须是空当前必须是有效的。如果范围以字节为单位,通过元素范围缩放 s。

_Inout_updates_(s)

_Inout_updates_bytes_(s)

对数组的指针,读取和写入这些函数。它是 s 元素的有效大小,并且在之前发送状态和状态。

_bytes_ 变量以字节为范围而不是元素。当范围不能表示为元素时,请使用此方法。例如,char 字符串将使用 _bytes_ 变量仅当一个相似的函数使用 wchar_t 时会。

_Inout_updates_z_(s)

指向以 null 终止并具有已知大小的数组的指针。元素引发通过终结器必须是空当前必须在之前有效的状态和发布状态。在 POST 值状态。假设与值不同在前状态;这包含 Null 结束符的位置。如果范围以字节为单位,通过元素范围缩放 s。

_Out_writes_to_(s,c)

_Out_writes_bytes_to_(s,c)

_Out_writes_all_(s)

_Out_writes_bytes_all_(s)

指向 s 元素的数组的指针。元素不必是有效的在调用以前的状态。在发送状态,直到 c的元素。Th 元素绑定有效。如果范围以字节为单位,由元素的范围缩放 s 和 c 或使用 _bytes_ 变量,定义如下:

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

换言之,缓冲区中的每个元素在 s 状态前的发送状态是有效的。例如:

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)

对数组的指针,读取和写入这些函数。它是 s 元素范围,一定适用于前状态,因此,c 元素在发送状态绑定有效。

_bytes_ 变量以字节为范围而不是元素。当范围不能表示为元素时,请使用此方法。例如,char 字符串将使用 _bytes_ 变量仅当一个相似的函数使用 wchar_t 时会。

_Inout_updates_all_(s)

_Inout_updates_bytes_all_(s)

对数组的指针,s 的大小的元素的函数读取和写入。定义作为等效于:

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

换言之,缓冲区中的每个元素在 s 状态前和后的发送状态是有效的。

_bytes_ 变量以字节为范围而不是元素。当范围不能表示为元素时,请使用此方法。例如,char 字符串将使用 _bytes_ 变量仅当一个相似的函数使用 wchar_t 时会。

_In_reads_to_ptr_(p)

对数组的一个指针表达式 p - _Curr_ (即 _Curr_中减去 p ) 由相应的语言标准定义的。在 p 之前的元素一定适用于前状态。

_In_reads_to_ptr_z_(p)

指向以 null 结尾的数组的指针表达式 p - _Curr_ (即 _Curr_中减去 p ) 由相应的语言标准定义的。在 p 之前的元素一定适用于前状态。

_Out_writes_to_ptr_(p)

对数组的一个指针表达式 p - _Curr_ (即 _Curr_中减去 p ) 由相应的语言标准定义的。在 p 之前的元素不必是有效的状态,并且在之前一定适用于发布状态。

_Out_writes_to_ptr_z_(p)

指向以 null 结尾的数组的指针表达式 p - _Curr_ (即 _Curr_中减去 p ) 由相应的语言标准定义的。在 p 之前的元素不必是有效的状态,并且在之前一定适用于发布状态。

可选指针参数

当指针参数注释包括 _opt_,则表示该参数可能为空。否则,执行与注释不包含 _opt_的版本相同。这是说明的指针参数 _opt_ 变量的列表:

_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_

输出指针参数

输出指针参数需要特殊表示法在消除参数的 null 岬和点对位置。

批注

说明

_Outptr_

参数不能是空的,并且在点发送状态位置不可以为 null且必须是有效的。

_Outptr_opt_

参数可能是空的,但在点发送状态位置不可以为 null且必须是有效的。

_Outptr_result_maybenull_

参数不能是空的,在点发送状态对位置可以为空。

_Outptr_opt_result_maybenull_

参数可能是空的,在点发送状态对位置可以为空。

在下表中,附加的子字符插入进一步限定注释含义的注释名称中。各子字符串是 _z、_COM_、_buffer_、_bytebuffer_和 _to_。

重要说明重要事项

如果您进行此类批注的接口都是 COM,请注意使用这些注释的COM窗体。不要使用任何其他类型的 COM 接口说明。

批注

说明

_Outptr_result_z_

_Outptr_opt_result_z_

_Outptr_result_maybenull_z_

_Ouptr_opt_result_maybenull_z_

返回的指针具有注释 _Null_terminated_。

_COM_Outptr_

_COM_Outptr_opt_

_COM_Outptr_result_maybenull_

_COM_Outptr_opt_result_maybenull_

返回的指针具有 COM 语义,并具有 _On_failure_ 发送条件返回的指针为空。

_Outptr_result_buffer_(s)

_Outptr_result_bytebuffer_(s)

_Outptr_opt_result_buffer_(s)

_Outptr_opt_result_bytebuffer_(s)

返回的指针指向一个大小为 s 元素或字节的有效缓冲区。

_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)

指向大小为 s 元素或字节缓冲区的点返回的指针中,第一个 c 有效。

某些接口约定假设输出参数在失败的 NULL。除显式 COM 代码,窗体下表更喜欢。对于 COM 代码,请使用上一节中列出的相应 COM 窗体。

批注

说明

_Result_nullonfailure_

修订其他注释。如果函数运行失败,结果设置为 null。

_Result_zeroonfailure_

修订其他注释。如果函数运行失败,结果设置为 null。

_Outptr_result_nullonfailure_

如果函数执行成功,则返回的指针指向一个有效的缓冲区,否则,指向空 此注释用于非可选参数。

_Outptr_opt_result_nullonfailure_

如果函数执行成功,则返回的指针指向一个有效的缓冲区,否则,指向空 此注释用于一个可选参数。

_Outref_result_nullonfailure_

如果函数执行成功,则返回的指针指向一个有效的缓冲区,否则,指向空 此注释为引用参数。

输出引用参数

通常引用参数用于输出参数。对于简单的参数输出引用—例如,int&-_Out_ 提供正确的语义。但是,当输出值为指针时——例如 int *& - 等同的指针为注释,_Outptr_ int ** 未提供正确的语义。若要简洁地表示指针类型的输出引用参数的语义,请使用这些复合注释:

批注

说明

_Outref_

结果一定适用于发布状态,且不能为 null。

_Outref_result_maybenull_

结果在发送状态必须是有效的,但可能为空。

_Outref_result_buffer_(s)

结果一定适用于发布状态,且不能为 null。指向大小为 s 元素有效的缓冲区。

_Outref_result_bytebuffer_(s)

结果一定适用于发布状态,且不能为 null。指向大小为 s 字节有效的缓冲区。

_Outref_result_buffer_to_(s, c)

结果一定适用于发布状态,且不能为 null。指向 s 元素缓冲区,它的第一个 c是有效的。

_Outref_result_bytebuffer_to_(s, c)

结果一定适用于发布状态,且不能为 null。指向 s 字节缓冲区,它的第一个 c是有效的。

_Outref_result_buffer_all_(s)

结果一定适用于发布状态,且不能为 null。指向大小为 s 有效元素有效的缓冲区。

_Outref_result_bytebuffer_all_(s)

结果一定适用于发布状态,且不能为 null。指向有效元素的有效 s 字节缓冲区。

_Outref_result_buffer_maybenull_(s)

结果在发送状态必须是有效的,但可能为空。指向大小为 s 元素有效的缓冲区。

_Outref_result_bytebuffer_maybenull_(s)

结果在发送状态必须是有效的,但可能为空。指向大小为 s 字节有效的缓冲区。

_Outref_result_buffer_to_maybenull_(s, c)

结果在发送状态必须是有效的,但可能为空。指向 s 元素缓冲区,它的第一个 c是有效的。

_Outref_result_bytebuffer_to_maybenull_(s,c)

结果在发送状态必须是有效的,但可能为空。指向 s 字节缓冲区,它的第一个 c是有效的。

_Outref_result_buffer_all_maybenull_(s)

结果在发送状态必须是有效的,但可能为空。指向大小为 s 有效元素有效的缓冲区。

_Outref_result_bytebuffer_all_maybenull_(s)

结果在发送状态必须是有效的,但可能为空。指向有效元素的有效 s 字节缓冲区。

返回值

函数的返回值类似_Out_ 参数,但在不同的取消引用级别上,因此,您不必考虑结果指针的概念。对于下面的批注,返回值为批注的对象——标量、指向结构的指针或指向缓冲区的指针。这些注释的语义和相应的注释 _Out_ 相同。

_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_

其他常见批注

批注

说明

_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)

参数、字段或结果在(包含) 从 low 到 hi的范围内 。应用所批注的对象与适当的状态之前或发送状态条件时等效于 _Satisfies_(_Curr_ >= low && _Curr_ <= hi)。

重要说明重要事项

虽然名称包含“in“和”out“,_In_和 _Out_的语义 执行 而不是 适用于这些注释。

_Pre_equal_to_(expr)

_Post_equal_to_(expr)

批注的正确值是 expr。应用所批注的对象与适当的状态之前或发送状态条件时等效于 _Satisfies_(_Curr_ == expr)。

_Struct_size_bytes_(size)

适用于结构或类声明。指示该类型有效对象可能比声明的类型大,size可能给出的字节数。例如:

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

缓冲区大小为 MyStruct * 类型参数 pM 的字节然后采用为:

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

相关资源

Team Blog 代码分析

请参见

参考

对函数行为进行批注

批注结构和类

对锁定行为进行批注

指定何时以及在何处应用批注

内部函数

最佳做法和示例 (SAL)

概念

了解 SAL

其他资源

使用 SAL 批注以减少 C/C++ 代码缺陷