What is the purpose of SAL (Source Annotation Language) and what is the difference between SAL 1 and SAL 2?
我理解使用的基础知识,这有助于突出传递给函数的每个变量的目的以及静态代码分析的各种其他内容,但它实际上有多大差异(忽略了参数要求的增加清晰度)该项目的其他程序员)?
如果我有以下原型:
_Success_(return == 1) int TestFunction( _In_ int* pTest,_Inopt_ char* pOptional );
这应该“告诉”静态分析器函数在成功操作时将返回1,pTest是一个指针,它必须不是nullptr,而pOptional是一个指针,可能是也可能不是nullptr.但是,静态分析器不能从函数定义本身获取此信息吗?此外,它对获得的信息如成功标准有何作用?
此外,为什么SAL 1和SAL 2之间存在差异,为什么微软决定改变他们命名宏的方式(即从__out到_Out_和__ccess到_Success_?)
我很抱歉,如果在MSDN上详细描述了这一点,但我无法在StackOverflow上找到它或任何其他问题并提供详细的答案,所以我想我会问我希望能满足我的好奇心.
在此先感谢您的时间!
解决方法
为什么要使用SAL而不仅仅是从源代码中推断出来?
关于使用SAL明确告知分析器有关参数行为等的详细信息,有多个答案.
>虽然分析器可以从实现中推断出参数行为,但它通常无法区分意图和实施事故之间的区别.作为开发人员,如果您明确说明了不同参数的预期用途,分析器可以验证您编写的实现是否满足您的意图,以及调用者是否正确使用它.
>当源代码不可用于分析时,这为静态分析器提供有关函数行为的信息,例如,作为Visual Studio,驱动程序工具包等一部分提供的各种头文件中声明的函数.
> SAL允许表达难以从源代码中推断出的概念,例如锁定用法和驱动程序中的IRQL要求.
>这也有助于与回调函数保持一致. 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之间有什么区别,为什么注释从__in重命名为_In_?
SAL的原始定义中的一些极端情况(例如__in)未与C井接合.新语法从一些较新的实现开始,确保它符合C和C语法的要求.
SAL 1和SAL 2之间的主要区别与SAL 2能够表达SAL 1不能表达的许多概念有关,而SAL 2更好地定义,特别是对于C,如上所述.