2. Operation

LCLint is invoked by listing files to be checked. Initialization files, command line flags, and stylized comments may be used to customize checking globally and locally.

The best way to learn to use LCLint, of course, is to actually use it (if you don't already have LCLint installed on your system, download it). Before you read much further in this document, I recommend finding a small C program. Then, try running:

lclint *.c

For the most C programs, this will produce a large number of messages. To turn off reporting for some of the messages, try:

lclint -weak *.c

The -weak flag is a mode flag that sets many checking parameters to select weaker checking than is done in the default mode. Other LCLint flags will be introduced in the following sections; a complete list is given in Appendix C.

2.1 Messages

The format and content of messages printed by LCLint can be customized by the user. A typical message is:

sample.c: (in function faucet)
sample.c:11:12: Fresh storage x not released before return
  A memory leak has been detected.  Newly-allocated or only-qualified storage
  is not released before the last reference to is it lost.  Use -mustfree to
  suppress message.
   sample.c:5:47: Fresh storage x allocated
The first line gives the name of the function in which the error is found. This is printed before the first message reported for a function. (The function context is not printed if -showfunc is used.)

The second line is the text of the message. This message reports a memory leak - storage allocated in a function is not deallocated before the function returns. The text is preceded by the file name, line and column number where the error is located. The column numbers errors iolving statements with no apparent effects (Section 10.3.1) and statements that ignore the result of a called function (Section 10.3.2).

10.3.1 Statements with No Effects

LCLint can report errors for statements that have no effect. (Controlled by noeffect.) Because of modifies clauses, LCLint can detect more errors than traditional checkers. Unless the noeffectuncon flag is on, errors are not reported for statements that involve calls to unconstrained functions since the unconstrained function may cause a modification.

Figure 22. Statements with no effect.

10.3.2 Ignored Return Values

LCLint reports an error when a return value is ignored. Checking may be controlled based on the type of the return value: retvalint controls reporting of ignored return values of type int, and retvalbool for return values of type bool, and retvalothers for all other types. A function statement may be cast to void to prevent this error from being reported.

Alternate types (Section 8.2.2) can be used to declare functions that return values that may safely be ignored by declaring the result type to alternately by void. Several functions in the standard library are specified to alternately return void to prevent ignored return value errors for standard library functions (e.g., strcpy) where the result may be safely ignored (see Apppendix F).

Figure 23 shows example of ignored return value errors reported by LCLint.

10.4 Unused Declarations

LCLint detects constants, functions, parameters, variables, types, enumerator members, and structure or union fields that are declared but never used. The flags constuse, fcnuse, paramuse, varuse, typeuse, enummemuse and fielduse control whether unused declaration errors are reported for each kind of declaration. Errors for exported declarations are reported only if topuse is on (see Section 10.5).

The /*@unused@*/ annotation can be used before a declaration to indicate that the item declared need not be used. Unused declaration errors are not reported for identifiers declared with unused.

10.5 Complete Programs

LCLint can be used on both complete and partial programs. When checking complete programs, additional checks can be done to ensure that every identifier declared by the program is defined and used, and that functions that do not need to be exported are declared static.

LCLint checks that all declared variables and functions are defined (controlled by compdef). Declarations of functions and variables that are defined in an external library, may be preceded by /*@external@*/ to suppress undefined declaration errors.

LCLint reports external declarations which are unused (Controlled by topuse). Which declarations are reported also depends on the declaration use flags (see Section 10.4).

The partial flag sets flags for checking a partial system. Top-level unused declarations, undefined declarations, and unnecessary external names are not reported if partial is set.

10.5.1 Unnecessary External Names

LCLint can report variables and functions that are declared with global scope (i.e., without using static), that are not used outside the file in which they are defined. In a stand-alone system, these identifiers should usually be declared using static to limit their scope. If the exportstatic flag is on, LCLint will report declarations that could have file scope. It should only be used when all relevant source files are listed on the LCLint command line; otherwise, variables and functions may be incorrectly identified as only used in the file scope since LCLint did not process the other file in which they are used.

10.5.2 Declarations Missing from Headers

A common practice in C programming styles, is that every function or variable exported by M.c is declared in M.h. If the exportheader flag is on, LCLint will report exported declarations in M.c that are not declared in M.h.

10.6 Compiler Limits

The ANSI Standard includes limits on minimum numbers that a conforming compiler must support. Whether of not a particular compiler exceeds these limits, it is worth checking that a program does not exceed them so that it may be safely compiled by other compilers. In addition, exceeding a limit may indicate a problem in the code (e.g., it is too complex if the control nest depth limit is exceeded) that should be fixed regardless of the compiler. The following limits are checked by LCLint. For each limit, the maximum value may be set from the command line (or locally using a stylized comment). If the ansilimits flag is on, all limits are checked with the minimum values of a conforming compiler.

includenest

Maximum nesting depth of file inclusion (#include). (ANSI minimum is 8)
controlnestdepth
Maximum nesting of compound statements, control structures. (ANSI minimum is 15)
numenummembers
Number of members in an enum declaration. (ANSI minimum is 127)
numstructfields
Number of fields in a struct or union declaration. (ANSI minimum is 127)






Since human beings themselves are not fully debugged yet, there will be bugs in your code no matter what you do.
- Chris Mason, Zero-defects memo (Microsoft Secrets, Cusumano and Selby)

Next Section Contents LCLint Home Page David Evans
Software Devices and Systems