SAL 是 Microsoft 源代码注释语言。 使用源代码批注,可以使代码背后的意图更加清晰。 这些注释还可以使用自动化的静态分析工具更准确地分析代码,显著减少误判。那么什么是批注,举个简单的例子,在函数参数或者返回值前边,有时候加 _in、 _out、 _inout之类的,这些就是批注。之前只是用的时候就会去查询各个批注的用法。用多了后干脆来一次大总结。下边是直接从msdn中转过来的,主要讲的是各个批注的用法和代表的含义。

Header Annotations

[This topic describes the annotations supported in the Windows headers through Windows 7. If you are developing for Windows 8, you should use the annotations described in SAL Annotations.]]

Header annotations describe how a function uses its parameters and return value. These annotations have been added to many of the Windows header files to help you ensure that you are calling the Windows API correctly. If you enable code analysis, which is available starting with the Visual Studio 2005, the compiler will produce level 6000 warnings if you are not calling these functions per the usage described through the annotations. You can also add these annotations in your own code to ensure that it is being called correctly. To enable code analysis in Visual Studio, see the documentation for your version of Visual Studio.

These annotations are defined in Specstrings.h. They are built on primitives that are part of the Standard Annotation Language (SAL) and implemented using _declspec("SAL_*").

There are two classes of annotations: buffer annotations and advanced annotations.

Buffer Annotations

Buffer annotations describe how functions use their pointers and can be used to detect buffer overruns. Each parameter may use zero or one buffer annotation. A buffer annotation is constructed with a leading underscore and the components described in the following sections.

Buffer size Description

(size)

Specifies the total size of the buffer. Use with _bcount and _ecount; do not use with _part. This value is the accessible space; it may be less than the allocated space.

(size,length)

Specifies the total size and initialized length of the buffer. Use with _bcount_part and _ecount_part. The total size may be less than the allocated space.

Buffer size units Description

_bcount

The buffer size is in bytes.

_ecount

The buffer size is in elements.

Direction Description

_in

The function reads from the buffer. The caller provides the buffer and initializes it.

_inout

The function both reads from and writes to buffer. The caller provides the buffer and initializes it. If used with _deref, the buffer may be reallocated by the function.

_out

The function writes to the buffer. If used on the return value or with _deref, the function provides the buffer and initializes it. Otherwise, the caller provides the buffer and the function initializes it.

Indirection Description

_deref

Dereference the parameter to obtain the buffer pointer. This parameter may not be NULL.

_deref_opt

Dereference the parameter to obtain the buffer pointer. This parameter can be NULL.

Initialization Description

_full

The function initializes the entire buffer. Use only with output buffers.

_part

The function initializes part of the buffer, and explicitly indicates how much. Use only with output buffers.

Required or optional buffer Description

_opt

This parameter can be NULL.

The following example shows the annotations for the GetModuleFileName function. The hModule parameter is an optional input parameter . ThelpFilename parameter is an output parameter; its size in characters is specified by the nSize parameter and its length includes the null-terminating character. The nSize parameter is an input parameter.

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

  

The following are the annotations defined in Specstrings.h. Use the information in the tables above to interpret their meaning.

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

Advanced Annotations

Advanced annotations provide additional information about the parameter or return value. Each parameter or return value may use zero or one advanced annotation.

Annotation Description

__blocksOn(resource)

The functions blocks on the specified resource.

__callback

The function can be used as a function pointer.

__checkReturn

Callers must check the return value.

__format_string

The parameter is a string that contains printf-style % markers.

__in_awcount(expr,size)

If the expression is true at exit, the size of the input buffer is specified in bytes. If the expression is false, the size is specified in elements.

__nullnullterminated

The buffer may be accessed up to and including the first sequence of two null characters or pointers.

__nullterminated

The buffer may be accessed up to and including the first null character or pointer.

__out_awcount(expr,size)

If the expression is true at exit, the size of the output buffer is specified in bytes. If the expression is false, the size is specified in elements.

__override

Specifies C#-style override behavior for virtual methods.

__reserved

The parameter is reserved for future use and must be zero or NULL.

__success(expr)

If the expression is true at exit, the caller can rely on all guarantees specified by other annotations. If the expression is false, the caller cannot rely on the guarantees. This annotation is automatically added to functions that return anHRESULT value.

__typefix(ctype)

Treat the parameter as the specified type rather than its declared type.

The following examples show the buffer and advanced annotations for the DeleteTimerQueueTimerFreeEnvironmentStrings, andUnhandledExceptionFilter functions.

C++

__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 特性,为 SAL 语法参考,并给出其使用的示例。具体的使用方法点开链接直接看。

VS中批注的使用的更多相关文章

  1. iClap分享:如何优雅的在 APP 中实现测试?

    开发团队常面临的问题有:内测 APP 时测出一堆 bug 写了很多文档,交到下一个人手中时问题总是不够清晰明了;版本发布公测时只能分发原生版本给团队和用户,无法快速反馈测试和体验结果;使用第三方工具, ...

  2. Java 添加、修改、读取、复制、删除Excel批注

    本文介绍通过Java程序来操作Excel批注的方法.操作内容包括批注添加(添加批注文本.背景色.字体.自适应等).修改.读取(文本.图片).复制.删除等. 工具:Free Spire.XLS for ...

  3. Java 获取Word批注所标记的文本和图片

    [环境配置] 本文将通过Java程序代码来展示如何来获取Word批注所标注的文本和图片.这里使用的Word Jar包工具是Free Spire.Doc for Java,在pom.xml中按如下步骤配 ...

  4. Linq世界走一走(LINQ TO XML)

    前言:Linq to xml是一种使用XML的新方法.从本质上来说,它采用了多种当前使用的XML处理技术,如DOM和XPath,并直接在.NET Framework内将它们组合为一个单一的编程接口.L ...

  5. 揭开.NET消息循环的神秘面纱(GetMessage()无法取得任何消息,就会进入Idle(空闲)状态,进入睡眠状态(而不是Busy Waiting)。当消息队列不再为空的时候,程序会自动醒过来)

    揭开.NET消息循环的神秘面纱(-) http://hi.baidu.com/sakiwer/item/f17dc33274a04df2a9842866 曾经在Win32平台下奋战的程序员们想必记得, ...

  6. Office文件的实质是什么

    Office文件的实质是什么 一.总结 一句话总结:对于一个Microsoft Office文件,其实质是一个Windows复合二进制文件(Windows Compound Binary File), ...

  7. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析

    Office文件的奥秘——.NET平台下不借助Office实现Word.Powerpoint等文件的解析 分类: 技术 2013-07-26 15:38 852人阅读 评论(0) 收藏 举报 Offi ...

  8. JXLS支持嵌套循环语法的数据导出说明

    今天在试验用Jxls 2.0导出嵌套循环数据时,第二层数据一直没有成功,最后确认是数据源结构不正确所致,现将这两种数据格式进行说明:假设模板中批注有这样两条循环语法: <jx:each(item ...

  9. 我要涨知识 —— TypeScript 常见面试题(一)

    1.ts 中的 any 和 unknown 有什么区别? unknown 和 any 的主要区别是 unknown 类型会更加严格:在对 unknown 类型的值执行大多数操作之前,我们必须进行某种形 ...

随机推荐

  1. Andrew N.G的机器学习公开课学习笔记(一):机器学习的动机与应用

    机器学习由对于人工智能的研究而来,是一个综合性和应用性学科,可以用来解决计算机视觉/生物学/机器人和日常语言等各个领域的问题,机器学习的目的是让计算机具有像人类的学习能力,这样做是因为我们发现,计算机 ...

  2. Java 基础【12】 压缩与解压缩

    Java.util.zip 提供用于读写标准 ZIP 和 GZIP 文件格式的类. 还包括使用 DEFLATE 压缩算法(用于 ZIP 和 GZIP 文件格式)对数据进行压缩和解压缩的类. 依赖 Jd ...

  3. CCF 201604-2 俄罗斯方块

    题目不难,但是感觉很有意思.一开始忘了把调试信息注释掉,WA了两次... 试题编号: 201604-2 试题名称: 俄罗斯方块 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 ...

  4. Win10 PC一周年更新正式版14393.447 32位/64位更新补丁KB3200970下载 Flash补丁Kb3202790下载

    微软在今天凌晨推送了Win10 PC一周年更新正式版14393.447,本次更新补丁代号为KB3200970,面向Win10一周年更新正式版的PC用户. 更新日志 • 提升了多媒体音频.远程桌面以及I ...

  5. bzoj2083【Poi2010】Intelligence test

    听说正解是链表,然而被我暴力水过了 先开vector记录每个数在原串中出现的位置 之后对于每个匹配串的每一位,找比当前位置大的第一个当前元素是哪个,有就更新,没有就"NIE" #i ...

  6. FFT小总结

    FFT实质上做的是循环卷积,ck=sigam(ai*bj,(i+j)%n=k),其中n是倍长后的长度,所以我们有时候需要的只是普通的卷积,我们就需要把原数组倍长,再用FFT求卷积,由于高位都是0,所以 ...

  7. HTML实现点击时的阴影(:active)(已解决iOS微信上无法使用)

    一般是用这个委类:active 参考:http://www.w3school.com.cn/cssref/selector_active.asp 但是业界上实现的效果中,今日头条的手机端网页却不是这样 ...

  8. C#把DataTable中数据一次插入数据库的方法

    现在实际的情况是这样的: 客户有一台打卡机,员工打卡的信息全部储存在打卡机的Access数据库里面,现在客户引入了一种新的管理系统,需要将Access数据库中的打卡数据同步到SQL Server数据库 ...

  9. [转]eclipse快捷键

    Ctrl+1 快速修复Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当前行到上一行(复制增加)Alt+↓ 当前行和下面一行交互位置(特别实用 ...

  10. SDL鼠标事件

    鼠标事件有这么多种,手柄的可以忽视,Sdl.SDL_KEYDOWN,Sdl.SDL_KEYUP,Sdl.SDL_MOUSEMOTION,Sdl.SDL_MOUSEBUTTONDOWN,Sdl.SDL_ ...