8

如标题中所问:

SAL(源注释语言)的目的是什么,SAL 1 和 SAL 2 有什么区别?

我了解使用的基础知识,这有助于突出传递给函数的每个变量的目的以及用于静态代码分析的各种其他内容,但它实际上有多大不同(忽略参数要求的日益清晰)项目中的其他程序员)?

如果我有以下原型:

_Success_(return == 1) 
int TestFunction( _In_ int* pTest, _Inopt_ char* pOptional );

这应该“告诉”静态分析器该函数将在成功操作后返回 1,这pTest是一个不能是的指针nullptrpOptional也是一个可能是也可能不是的指针nullptr。但是,静态分析器不能从函数定义本身获取这些信息吗?此外,它如何处理获得的信息,例如成功标准?

此外,为什么 SAL 1 和 SAL 2 之间存在差异,为什么微软决定改变他们命名宏的方式(即 from __outto_Out___successto _Success_?)

很抱歉,如果 MSDN 上某处对此进行了详细描述,但我无法在 StackOverflow 上找到它或任何其他问题的详细答案,所以我想我会问,希望能满足我的好奇心。

在此先感谢您的时间!

4

1 回答 1

12

我在您的问题中阅读了多个问题,希望我得到了所有问题:

为什么要使用 SAL 而不仅仅是从源头推断?

关于使用 SAL 明确告诉分析器有关参数行为等的详细信息,有多种答案。

  1. 尽管分析器可以从实现中推断出参数行为,但它通常无法区分实现的意图和意外。作为开发人员,如果您明确说明不同参数的预期用途,分析器既可以验证您编写的实现是否满足您的意图,也可以验证调用者是否正确使用它。

  2. 当源代码不可用于分析时,这会为静态分析器提供有关函数行为的信息,例如作为 Visual Studio 的一部分提供的各种头文件中声明的函数、驱动程序包等。

  3. SAL 允许表达仅从源代码中难以或不可能推断出的概念,例如驱动程序中的锁使用和 IRQL 要求。

  4. 这也有助于与回调函数保持一致。Windows 头文件描述的某些框架可能会声明一组回调函数,因此 Windows 框架将调用在其他地方(应用程序、驱动程序等)定义的那些回调函数。因此,Windows 永远不会看到被调用函数的来源,回调函数定义永远不会看到调用者。

分析器从Success获得什么信息?

这与您编写的案例无关。但是,在有输出参数的情况下(例如Out和family),这意味着如果函数不成功,则调用者不能依赖输出注释。例如:

_Success_(return) bool GetASmallInt(_Out_range_(0, 10) int& an_int);

如果 GetASmallInt 返回 true,则 an_int 将介于 0 和 10 之间,包括 0 和 10。如果它返回 false,则不存在这样的保证,并且该变量甚至可能还没有被函数初始化。

SAL 1 和 SAL 2 有什么区别,为什么注释从__into重命名_In_

SAL 的原始定义中的一些极端情况(例如 __in)与 C++ 没有很好的结合。新语法从一些较新的实现开始,确保它符合 C 和 C++ 语法的要求。

SAL 1 和 SAL 2 之间的主要区别在于 SAL 2 能够表达 SAL 1 无法表达的许多概念,并且 SAL 2 的定义更好,尤其是在 C++ 方面,如上所述。

于 2013-05-05T18:05:01.390 回答