标头批注

[本主题介绍 Windows 7 的 Windows 标头中支持的批注。 如果要针对Windows 8进行开发,则应使用 SAL 注释中所述的注释。]

标头注释描述函数如何使用其参数和返回值。 这些注释已添加到许多 Windows 头文件,以帮助你确保正确调用 Windows API。 如果启用代码分析(从 Visual Studio 2005 开始可用),则如果不按照注释中所述的用法调用这些函数,编译器将生成 6000 级警告。 还可以在自己的代码中添加这些注释,以确保正确调用它。 若要在 Visual Studio 中启用代码分析,请参阅 Visual Studio 版本的文档。

这些批注在 Specstrings.h 中定义。 它们基于属于标准批注语言的基元 (SAL) 并使用 _declspec("SAL_*")实现。

有两类批注:缓冲区批注和高级批注。

缓冲区批注

缓冲区注释描述函数如何使用其指针,并可用于检测缓冲区溢出。 每个参数都可以使用零个或一个缓冲区批注。 缓冲区批注是使用前导下划线和以下部分所述的组件构造的。

缓冲区大小 说明
(大小)
指定缓冲区的总大小。 与 _bcount 和 _ecount 一起使用;不要与 _part 一起使用。 此值是可访问空间;它可能小于分配的空间。
(大小长度)
指定缓冲区的总大小和初始化长度。 与 _bcount_part 和 _ecount_part 一起使用。 总大小可能小于分配的空间。
缓冲区大小单位 说明
_bcount
缓冲区大小以字节为单位。
_ecount
缓冲区大小以元素为单位。
方向 说明
_in
函数从缓冲区进行读取。 调用方提供缓冲区并对其进行初始化。
_inout
函数同时从缓冲区读取和写入缓冲区。 调用方提供缓冲区并对其进行初始化。 如果与 _deref 一起使用,则缓冲区可由 函数重新分配。
_out
函数写入缓冲区。 如果在返回值上使用或与_deref一起使用,函数将提供缓冲区并初始化它。 否则,调用方提供缓冲区,函数初始化它。
间接寻址 说明
_deref
取消引用 参数以获取缓冲区指针。 此参数可能不是 NULL
_deref_opt
取消引用 参数以获取缓冲区指针。 此参数可以为 NULL。
初始化 说明
_全
函数初始化整个缓冲区。 仅与输出缓冲区一起使用。
_部分
函数初始化部分缓冲区,并显式指示缓冲区的量。 仅与输出缓冲区一起使用。
必需或可选缓冲区 说明
_选择
此参数可以为 NULL。

以下示例演示 GetModuleFileName 函数的注释。 hModule 参数是可选的输入参数 。 lpFilename 参数是输出参数;其大小(以字符为单位)由 nSize 参数指定,其长度包括 null 终止字符。 nSize 参数是输入参数。

DWORD
WINAPI
GetModuleFileName(
    __in_opt HMODULE hModule,
    __out_ecount_part(nSize, return + 1) LPTSTR lpFilename,
    __in DWORD nSize
    );

以下是 Specstrings.h 中定义的批注。 使用上表中的信息来解释其含义。

__bcount (大小)
__bcount_opt (大小)
__deref_bcount (大小)
__deref_bcount_opt (大小)
__deref_ecount (大小)
__deref_ecount_opt (大小)
__deref_in
__deref_in_bcount (大小)
__deref_in_bcount_opt (大小)
__deref_in_ecount (大小)
__deref_in_ecount_opt (大小)
__deref_in_opt
__deref_inout
__deref_inout_bcount (大小)
__deref_inout_bcount_full (大小)
__deref_inout_bcount_full_opt (大小)
__deref_inout_bcount_opt (大小)
__deref_inout_bcount_part (大小长度)
__deref_inout_bcount_part_opt (大小长度)
__deref_inout_ecount (大小)
__deref_inout_ecount_full (大小)
__deref_inout_ecount_full_opt (大小)
__deref_inout_ecount_opt (大小)
__deref_inout_ecount_part (大小长度)
__deref_inout_ecount_part_opt (大小长度)
__deref_inout_opt
__deref_opt_bcount (大小)
__deref_opt_bcount_opt (大小)
__deref_opt_ecount (大小)
__deref_opt_ecount_opt (大小)
__deref_opt_in
__deref_opt_in_bcount (大小)
__deref_opt_in_bcount_opt (大小)
__deref_opt_in_ecount (大小)
__deref_opt_in_ecount_opt (大小)
__deref_opt_in_opt
__deref_opt_inout
__deref_opt_inout_bcount (大小)
__deref_opt_inout_bcount_full (大小)
__deref_opt_inout_bcount_full_opt (大小)
__deref_opt_inout_bcount_opt (大小)
__deref_opt_inout_bcount_part (大小长度)
__deref_opt_inout_bcount_part_opt (大小长度)
__deref_opt_inout_ecount (大小)
__deref_opt_inout_ecount_full (大小)
__deref_opt_inout_ecount_full_opt (大小)
__deref_opt_inout_ecount_opt (大小)
__deref_opt_inout_ecount_part (大小长度)
__deref_opt_inout_ecount_part_opt (大小长度)
__deref_opt_inout_opt
__deref_opt_out
__deref_opt_out_bcount (大小)
__deref_opt_out_bcount_full (大小)
__deref_opt_out_bcount_full_opt (大小)
__deref_opt_out_bcount_opt (大小)
__deref_opt_out_bcount_part (大小长度)
__deref_opt_out_bcount_part_opt (大小长度)
__deref_opt_out_ecount (大小)
__deref_opt_out_ecount_full (大小)
__deref_opt_out_ecount_full_opt (大小)
__deref_opt_out_ecount_opt (大小)
__deref_opt_out_ecount_part (大小长度)
__deref_opt_out_ecount_part_opt (大小长度)
__deref_opt_out_opt
__deref_out
__deref_out_bcount (大小)
__deref_out_bcount_full (大小)
__deref_out_bcount_full_opt (大小)
__deref_out_bcount_opt (大小)
__deref_out_bcount_part (大小长度)
__deref_out_bcount_part_opt (大小长度)
__deref_out_ecount (大小)
__deref_out_ecount_full (大小)
__deref_out_ecount_full_opt (大小)
__deref_out_ecount_opt (大小)
__deref_out_ecount_part (大小长度)
__deref_out_ecount_part_opt (大小长度)
__deref_out_opt
__ecount (大小)
__ecount_opt (大小)
__in
__in_bcount (大小)
__in_bcount_opt (大小)
__in_ecount (大小)
__in_ecount_opt (大小)
__in_opt
__inout
__inout_bcount (大小)
__inout_bcount_full (大小)
__inout_bcount_full_opt (大小)
__inout_bcount_opt (大小)
__inout_bcount_part (大小长度)
__inout_bcount_part_opt (大小长度)
__inout_ecount (大小)
__inout_ecount_full (大小)
__inout_ecount_full_opt (大小)
__inout_ecount_opt (大小)
__inout_ecount_part (大小长度)
__inout_ecount_part_opt (大小长度)
__inout_opt
__out
__out_bcount (大小)
__out_bcount_full (大小)
__out_bcount_full_opt (大小)
__out_bcount_opt (大小)
__out_bcount_part (大小长度)
__out_bcount_part_opt (大小长度)
__out_ecount (大小)
__out_ecount_full (大小)
__out_ecount_full_opt (大小)
__out_ecount_opt (大小)
__out_ecount_part (大小长度)
__out_ecount_part_opt (大小长度)
__out_opt

高级批注

高级注释提供有关参数或返回值的其他信息。 每个参数或返回值都可以使用零个或一个高级注释。

Annotation 说明
__blocksOn (资源)
函数对指定资源进行阻止。
__回调
函数可用作函数指针。
__checkReturn
调用方必须检查返回值。
__format_string
参数是包含 printf 样式百分比标记的字符串。
__in_awcount (exprsize)
如果表达式在退出时为 true,则输入缓冲区的大小以字节为单位指定。 如果表达式为 false,则会在 元素中指定大小。
__nullnullterminated
可以最多访问缓冲区,包括两个 null 字符或指针的第一个序列。
__nullterminated
缓冲区可以最多访问,包括第一个 null 字符或指针。
__out_awcount (exprsize)
如果表达式在退出时为 true,则输出缓冲区的大小以字节为单位指定。 如果表达式为 false,则会在 元素中指定大小。
__覆盖
指定虚拟方法的 C#样式替代行为。
__保留
参数保留供将来使用,必须为零或 NULL
__success (expr)
如果表达式在退出时为 true,则调用方可以依赖于其他注释指定的所有保证。 如果表达式为 false,则调用方不能依赖于保证。 此批注会自动添加到返回 HRESULT 值的函数中。
__typefix (ctype)
将 参数视为指定的类型,而不是其声明的类型。

以下示例演示 DeleteTimerQueueTimerFreeEnvironmentStringsUnhandledExceptionFilter 函数的缓冲区和高级注释。

__checkReturn
BOOL
WINAPI
DeleteTimerQueueTimer(
    __in_opt HANDLE TimerQueue,
    __in     HANDLE Timer,
    __in_opt HANDLE CompletionEvent
    );

BOOL
WINAPI
FreeEnvironmentStrings(
    __in __nullnullterminated LPTCH
    );

__callback
LONG
WINAPI
UnhandledExceptionFilter(
    __in struct _EXCEPTION_POINTERS *ExceptionInfo
    );

SAL 批注

演练:分析 C/C++ 代码的缺陷