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.
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.)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 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).
Figure 22. Statements with no effect.
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.
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.
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.
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)