I read multiple questions in your question, hopefully I got them all:
Why use SAL and not just deduce from source?
There are multiple answers as to the point of explicitly telling the analyzer details about parameter behavior, etc., with SAL.
Although an analyzer can deduce parameter behavior from the implementation, it often can't tell the difference between intent and accidents of implementation. As a developer, if you explicitly state the intended purpose of different parameters, the analyzer can both validate that you wrote an implementation that fulfilled your intent and also that callers are using it correctly.
This gives static analyzers information about function behavior when the source code isn't available to analyze, for instance the functions declared in various header files shipped as part of Visual Studio, driver kits, etc.
SAL allows expression of concepts that are difficult to impossible to deduce from source code only, such as lock usage and IRQL requirements in drivers.
This also assists in consistency with callback functions. Some frameworks described by the Windows headers may declare a set of callback functions, so the Windows framework will call those callback functions defined elsewhere (applications, drivers, etc.). So Windows never sees the source for the called functions, and the callback function definitions never see the callers.
What information does the analyzer get from Success?
This is not really relevant in the case you wrote. However in cases where there are output parameters (e.g. Out and family), it means that if the function does not succeed, the caller cannot rely on the output annotations. So for instance:
_Success_(return) bool GetASmallInt(_Out_range_(0, 10) int& an_int);
If GetASmallInt returns true, an_int will be between 0 and 10, inclusive. If it returns false, no such guarantee exists, and the variable may not even have been initialized by the function.
What is the difference between SAL 1 and SAL 2 and why were the annotations renamed from __in
to _In_
?
Some corner cases in the original definition of SAL (e.g. __in) didn't mesh with C++ well. The new syntax started off with some newer implementation that made sure it would be consistent with the requirements of both the C and C++ grammars.
The main difference between SAL 1 and SAL 2 has to do with SAL 2 being able to express a lot of concepts that SAL 1 cannot, and SAL 2 is better defined, especially with respect to C++, as noted above.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…