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

本文介绍对简单的函数参数标量的批注的典型用途和指向结构和选件类和大多数缓冲区。本文还显示批注的常见使用模式。有关功能相关的其他批注,请参见 对函数行为进行批注"

指针参数

对批注下表中,那么,当指针参数进行批注时,该分析器报告错误,如果指针为空。这适用于指针和于点的所有数据项。

批注

描述

_In_

批注是标量,结构,指向结构的指针等的输入参数。在简单的标量可以显式使用。该参数必须是有效的前状态,并且不会修改。

_Out_

批注是标量,结构,指向结构的指针等的输出参数。不要将此于不能返回值 (例如的对象,通过值传递的标量。该参数不必是有效的前状态,但是一定适用于后状态。

_Inout_

杂注将函数更改的参数。在调用之前,它必须是有效的前状态和后期状态,但是,则假定具有不同的值。必须应用于一个可修改的值。

_In_z_

对于使用作为输入的一个 null 终止的字符串的指针。该字符串必须是有效的前状态。PSTR变量,已具有正确的批注,首选方法。

_Inout_z_

对要修改的一个 null 终止的字符数组的指针。在调用,但是,该值假定已更改前后,它必须是有效的。null 结束符可能已被移动,但是,到原始 null 结束符的元素只能访问。

_In_reads_(s)

_In_reads_bytes_(s)

对于数组的指针,由函数读取。数组属于范围 s 元素,必须是有效的。

_bytes_ 变量以字节为范围代替元素。只有 + 当该范围不能表示为元素时,请使用此方法。例如,char 字符串将使用 _bytes_ 变量,只有 + 当使用 wchar_t 的一个类似的函数一样。

_In_reads_z_(s)

指向以 null 终止的并且有一个已知大小的数组的指针。为 null 结束符或 s 的元素,如果没有 null 结束符必须是有效的前状态。如果该大小 (以字节为单位) 知道,请由元素范围称为 s。

_In_reads_or_z_(s)

指向以 null 终止或具有已知大小的数组的指针或两个。为 null 结束符或 s 的元素,如果没有 null 结束符必须是有效的前状态。如果该大小 (以字节为单位) 知道,请由元素范围称为 s。(用于 strn 系列。)

_Out_writes_(s)

_Out_writes_bytes_(s)

对数组的指针 s 元素 (resp。将函数编写的字节)。数组元素不必是有效的前状态,并且,适用于后状态元素数是未指定的。如果在参数的批注在后期状态类型,它们适用。例如,考虑下面的代码。

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 终止的并且有一个已知大小的数组的指针。元素引发通过结束符必须是空当前必须有效的前状态和后期状态。在这个后期状态的值将假定与该之前状态的值不同;这包括 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_

参数不能为空,则,并将后状态指向位置不为空,并且必须是有效的。

_Outptr_opt_

参数可以为空,但是,在该后状态指向位置不为空,并且必须是有效的。

_Outptr_result_maybenull_

参数不能为空,则,并将后状态指向位置可以为空。

_Outptr_opt_result_maybenull_

参数可以为 null,因此,在该后状态指向位置可以为空。

在下表中,附加子字符串插入到批注名称来限定该批注的含义。各个子字符串是 _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_

修改其他批注。如果函数失败,则结果设置为零。

_Outptr_result_nullonfailure_

返回的指针指向有效的缓冲区,如果函数成功,则返回 null,如果函数失败。此批注用于非可选参数。

_Outptr_opt_result_nullonfailure_

返回的指针指向有效的缓冲区,如果函数成功,则返回 null,如果函数失败。此批注是为可选参数。

_Outref_result_nullonfailure_

返回的指针指向有效的缓冲区,如果函数成功,则返回 null,如果函数失败。此批注用于引用参数。

输出引用参数

通常引用参数是为输出参数。对于简单的输出形参 (例如,int&引用—_Out_ 提供正确的语义。但是,那么,当输出值是指针 (例如 int *&—等同的指针批注,如 _Outptr_ int ** 不提供正确的语义。简明表示输出引用参数语义指针类型的,请使用这些复合批注:

批注

描述

_Outref_

结果一定适用于后状态,并且不能为空。

_Outref_result_maybenull_

结果必须是有效的。之后,状态,但可能为空在后期状态。

_Outref_result_buffer_(s)

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

_Outref_result_bytebuffer_(s)

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

_Outref_result_buffer_to_(s, c)

结果一定适用于后状态,并且不能为空。指向 s 元素缓冲区,第一 c 有效。

_Outref_result_bytebuffer_to_(s, c)

结果一定适用于后状态,并且不能为空。指向的 s 字节缓冲区第一 c 有效。

_Outref_result_buffer_all_(s)

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

_Outref_result_bytebuffer_all_(s)

结果一定适用于后状态,并且不能为空。指向 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)

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

_Outref_result_buffer_all_maybenull_(s)

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

_Outref_result_bytebuffer_all_maybenull_(s)

结果必须是有效的。之后,状态,但可能为空在 POST 状态。指向 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_not 适用于这些批注。

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

相关资源

代码分析团队博客

请参见

参考

对函数行为进行批注

批注结构和类

对锁定行为进行批注

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

内部函数

最佳做法和示例 (SAL)

概念

了解 SAL

其他资源

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