Exportar (0) Imprimir
Expandir todo

SAL Annotations

If you examine the library header files, you will notice some unusual annotations such as __in_z and __out_ecount_part. These are examples of Microsoft's standard source code annotation language (SAL), which provides a set of annotations to describe how a function uses its parameters—the assumptions it makes about them, and the guarantees it makes upon finishing. The header file <sal.h> defines the annotations.

Annotations may be placed before either a function parameter's type or its return type, and describe the function's behavior regarding the parameter or return value. There are two classes of annotations: buffer annotations and advanced annotations. Buffer annotations describe how functions use their pointer parameters, and advanced annotations either describe complex/unusual buffer behavior, or provide additional information about a parameter that is not otherwise expressible.

Buffer Annotations

The most important annotations provide a consistent way to annotate buffer parameters or return values for a function. Each of these annotations describes a single buffer (which could be a string, a fixed-length or variable-length array, or just a pointer) that the function interacts with—where it is, how large it is, how much is initialized, and what the function does with it.

The appropriate macro for a given buffer can be constructed using the table below. Pick the appropriate values from each category, and combine them together with a leading underscore. Some combinations of values do not make sense as buffer annotations. Only meaningful annotations can be added to your code; for a list of these, see the buffer annotation definitions section in <sal.h>.

Only a single buffer annotation should be used for each parameter.

Category Possible choices

Level

(none)

_deref

_deref_opt

Usage

(none)

_in

_out

_inout

Size

(none)

_ecount

_bcount

Output

(none)

_full

_part

Null-termination

_z

_nz

Optional

(none)

_opt

Parameters

(none)

(size)

(size,length)

The various categories and their respective choices are described below.

Level

Describes the buffer pointer's level of indirection from the parameter or return value p.

(none)

p is the buffer pointer.

_deref

*p is the buffer pointer. p must not be NULL.

_deref_opt

*p may be the buffer pointer. p may be NULL, in which case the rest of the annotation is ignored.

Usage

Describes how the function uses the buffer.

(none)

The buffer is not accessed. If used on the return value or with _deref, the function will provide the buffer, and it will be uninitialized at exit. Otherwise, the caller must provide the buffer. This should only be used for alloc and free functions.

_in

The function will only read from the buffer. The caller must provide the buffer and initialize it. Cannot be used with _deref.

_out

The function will only write to the buffer. If used on the return value or with _deref, the function will provide the buffer and initialize it. Otherwise, the caller must provide the buffer, and the function will initialize it.

_inout

The function may freely read from and write to the buffer. The caller must provide the buffer and initialize it. If used with _deref, the buffer may be reallocated by the function.

Size

Describes the total size of the buffer. This may be less than the space actually allocated for the buffer, in which case it describes the accessible amount.

(none)

No buffer size is given. If the type specifies the buffer size (such as with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is one element long. Must be used with _in, _out, or _inout.

_ecount

The buffer size is an explicit element count.

_bcount

The buffer size is an explicit byte count.

Output

Describes how much of the buffer will be initialized by the function. For _inout buffers, this also describes how much is initialized at entry. Omit this category for _in buffers; they must be fully initialized by the caller.

(none)

The type specifies how much is initialized. For instance, a function initializing an LPWSTR must null-terminate the string.

_full

The function initializes the entire buffer.

_part

The function initializes part of the buffer, and explicitly indicates how much.

Null-Termination

States if the presence of a '\0' marks the end of valid elements in the buffer.

_z

A '\0' indicates the end of the buffer.

_nz

The buffer may not be null-terminated and a '\0' does not indicate the end of the buffer.

Optional

Describes if the buffer itself is optional.

(none)

The pointer to the buffer must not be NULL.

_opt

The pointer to the buffer might be NULL. It will be checked before being dereferenced.

Parameters

Gives explicit counts for the size and length of the buffer.

(none)

There is no explicit count. Use when neither _ecount nor _bcount is used.

(size)

Only the buffer's total size is given. Use with _ecount or _bcount but not _part.

(size,length)

The buffer's total size and initialized length are given. Use with _ecount_part and _bcount_part.

Example

// Buffer Annotation Examples

LWSTDAPI_(BOOL) StrToIntExA(
    LPCSTR pszString,    // No annotation required, const implies __in.
    DWORD dwFlags,
    __out int *piRet     // A pointer whose dereference will be filled 
);

void MyPaintingFunction(
    __in HWND hwndControl,      // An initialized read-only parameter.
    __in_opt HDC hdcOptional,   // An initialized read-only parameter
                                //  that might be NULL.
    __inout IPropertyStore *ppsStore  // An initialized parameter that
                                // may be freeely used and modified.
);

LWSTDAPI_(BOOL) PathCompactPathExA(
    __out_ecount(cchMax) LPSTR pszOut,   // A string buffer with cchMax
                      // elements that will be null-terminated on exit.
    LPCSTR pszSrc,                       // No annotation required,
                                         //  const implies __in.
    UINT cchMax,
    DWORD dwFlags
);

HRESULT SHLocalAllocBytes(
    size_t cb,
    __deref_bcount(cb) T **ppv  // A pointer whose dereference will be 
                          // set to uninitialized buffer with cb bytes.
);

__inout_bcount_full(cb) // A buffer with cb elements that is fully 
                        //  initialized at entry and exit, and may be
                        //  written to by this function.

__out_ecount_part(count, *countOut) // A buffer with count elements
                       // that will be partially initialized by this
                       //  function. The function indicates how much it
                       //  initialized by setting *countOut.

Advanced Annotations

Advanced annotations describe behavior that is not expressible with the regular buffer macros. These may be used either to annotate buffer parameters that involve complex or conditional behavior, or to enrich existing annotations with additional information.

__success(expr) f

expr indicates whether function f succeeded or not. If expr is true at exit, all the function's guarantees (as given by other annotations) must hold. If expr is false at exit, the caller should not expect any of the function's guarantees to hold. If not used, the function must always satisfy its guarantees. Added automatically to functions that indicate success in standard ways, such as by returning an HRESULT.

__nullterminated p

Pointer p is a buffer that may be read or written up to and including the first null character or pointer. May be used on typedefs that mark valid (properly initialized) instances of that type as being null-terminated.

__nullnullterminated p

Pointer p is a buffer that may be read or written up to and including the first sequence of two null characters or pointers. May be used on typedefs that mark valid instances of that type as being double-null-terminated.

__reserved v

Value v must be 0 or NULL. Reserved for future use.

__checkReturn v

Return value v must not be ignored by callers of this function.

__typefix(ctype) v

Value v should be treated as an instance of ctype, rather than its declared type.

__override f

Specify C#-style 'override' behavior for overriding virtual methods.

__callback f

Function f can be used as a function pointer.

__format_string p

Pointer p is a string that contains % markers in the style of printf.

__blocksOn(resource) f

Function f blocks on the resource resource.

__fallthrough

Annotates switch statement labels where fall-through is desired, to distinguish from forgotten break statements.

Example

// Advanced Annotation Examples

__success(return == TRUE) LWSTDAPI_(BOOL) 
PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath)
// pszBuf is only guaranteed to be null-terminated when TRUE is returned.

typedef __nullterminated WCHAR* LPWSTR
// Initialized LPWSTRs are null-terminated strings.

__out_ecount(cch) __typefix(LPWSTR) void *psz
// psz is a buffer parameter which will be a null-terminated WCHAR
//  string at exit, and which initially contains cch WCHARs.

See Also

Adiciones de comunidad

AGREGAR
Mostrar:
© 2014 Microsoft