共用方式為


Best Practices for Using Annotations

The following guidelines represent best practices for applying annotations:

Use annotations in a way that makes sense for your project.

The correct approach to using annotations is the one that works best for your project:

  • For some development projects, it might make sense to proactively examine every function in the program and apply the appropriate annotations and other recommended changes.

    This takes some effort but helps to assure that every bug that PREfast for Drivers (PFD) could find is found and identified. Done correctly, this minimizes false positives as well. In addition, when you examine your code this closely it can help you to understand the functions better and can help you to catch potential problems with their usage.

  • If time and resources are limited, it might make sense to first run PFD on existing code and then apply whatever annotations are needed to suppress false positives.

    This does not necessarily find all of the problems that the proactive approach might find, but it is a valid way to use PREfast.

The time that you can save when PFD finds even a few problems is enough to compensate for the effort of applying annotations, compared to the time that is required to debug those problems by using conventional methods. Over time, the value of being more proactive and applying annotations earlier in the development cycle should become obvious.

Use annotations to describe a successful function call.

Annotations should reflect a successful call to the function. PFD should catch inherently ill-formed or unsuccessful calls, not just calls that cause the system to crash. Annotations should reflect the intent of the function as reflected by its interface, not the actual implementation of the function.

A common example is optional parameters. A lot of code is written that checks to see if a parameter is NULL. But is a NULL parameter genuinely optional? For example:

  • If the function ignores the NULL parameter and proceeds to do something useful, the parameter is optional.

  • If the function returns an error when it is called with a NULL parameter, the parameter is not optional. Instead, the function defends itself from bad usage.

If PFD can tell the caller that a potentially NULL parameter will cause the function to fail, PFD can also find the potential bug rather than having the bug surface at runtime in some obscure circumstance that is hard to test for. Having a function defend itself against bad parameters is good practice, but the fact that it does so does not make the parameter "optional" in this sense.

As functions become more complex, their behavior when they fail (or partially fail) might need to be described as part of the annotations. For finer control of the effects of failure, you can use the __success annotation. For more information, see Success and Failure Annotations.

Consider how a function might evolve.

When you add annotations to a function, you must consider how the function might evolve. The annotation should reflect the intention of the function designer, not necessarily the current implementation of the function.

For example, a function, as implemented, might work correctly with parameter values that are different from those that were intended. Although it is tempting to annotate the function based upon what the code actually does, the designer of the function might be aware of future requirements, such as the need to maintain some restriction to support some future enhancement or pending system requirement.

Resolve conflicts between a function and its documentation.

Annotations can expose two kinds of conflicts between a function's implementation and its documentation:

  • The code and the documentation are factually inconsistent; one or the other must be fixed.

  • The documentation describes as required something that is true about the implementation but is not enforced, that is, an incorrect function call would succeed.

In this case, the function designer must decide whether to revise the documentation or use annotations to enforce the documented behavior of the function, to ensure that the function is used correctly as intended.

Use the /W4, /WX, and /Wp64 compiler flags.

The compiler also detects a number of potential errors, not all of which are detected by PFD. It is good practice to use the following compiler flags:

  • /W4
    Warn at level 4

  • /WX
    Make warnings fatal

  • /Wp64
    Warn on 64-bit portability issues

Minimize the scope of any #pragma warning annotations that are used to suppress false-positive warnings from the compiler.

Use only the general purpose annotations and driver annotations for driver code.

Annotations are implemented in different ways, depending on the exact version of the analysis tools you are using. Documentation and header file comments that mention __declspec or annotations that use a square-bracket notation similar to those used in C# can be ignored for the purposes of using PREfast for Drivers (PFD). Only the General-Purpose Annotations and Driver Annotations are officially supported for annotating driver code.

 

 

Send comments about this topic to Microsoft

Build date: 5/3/2011