C + + code static analysis tool Splint

Source: Internet
Author: User

1. Introduction

Recently, the static program analysis tool Pc-lint has been used in the project to realize its convenience for developers in project implementation. Pc-lint is a static analysis tool for the C + + language, the Windows platform, and Flexelint is a pc-lint version for other platforms. Since Pc-lint/flexelint is a commercial program analysis tool, it is not easy for everyone to learn and use, so I will introduce a C language for the open source program static analysis tool--splint.

2. Static program Analysis

The first thing to say is "Static program analysis", static procedure analysis refers to the use of automated tool software to check the program source code to analyze the program behavior of the technology, applied to program correctness check, security flaw detection, program optimization and so on. It is characterized by the non-execution of the program, instead, by executing the program in a real or simulated environment, the method of analysis is called "Dynamic program Analysis".

Under what circumstances do we need to perform static program analysis? Static program analysis is often used as a phase of the code review process in a multi-participant project, where static analysis can be performed after writing a portion of the code, and the analysis process does not need to execute the entire program, which helps to identify the following issues early in the project: variables declared but not used, variable type mismatch, variables not defined before use , unreachable code, Dead loops, array out of bounds, memory leaks, and so on.

The static analysis tool parses the code after it has been compiled. We ask: What is the difference between a static analysis tool and a compiler? Static analysis tools, compared to compilers, have more stringent code checks, such as array out-of-bounds access, memory leaks, improper use of type conversion and other issues can be checked out by static analysis tools, we can even define the analysis tool in the analysis standard code to write specifications, An alarm is thrown when code that does not conform to the writing specification is detected, and these functions are not in the compiler.

Since static analysis tools play a small role, why not have static analysis in the compiler? For this problem, S. C. Johnson, the author of Lint, the oldest static analysis tool, gave his answer in his 1978 paper, Lint, a C program Checker: "The separation of functions between Lint and C compilers has historical reasons, There is also a realistic meaning. The compiler is responsible for the rapid and efficient conversion of C source program into an executable file, do not do type checking code (especially for the separately compiled program), is beneficial to achieve fast and efficient. Lint does not require "efficient", and it can take more time to examine the code in more depth and detail. ”

For null pointer extraction, undefined variable usage, type conversion, memory management, function interface definition, and so on, we can develop different detection standards in static analysis tools, the following diagram illustrates the relationship between the detection standard and the cost of the splint operation when using splint for analysis, and from another perspective, Also illustrates the relationship between the static analysis tool and the compiler:

Splint

After mastering the concepts of "static analysis", we look at splint.

Under the Linux command line, the use of splint is very simple, the detection of file *.c, as long as this use can be:

Splint *.C

1.splint message

We use the following examples to understand the typical splint alarm information:

1//splint_msg.c
2 int func_splint_msg1 (void)
3 {
4 int A;
5 return 0;
6}
7 int func_splint_msg2 (void)
8 {
9 int* a = (int*) malloc (sizeof (int));
Ten a = NULL;
return 0;
12}

After running splint splint_msg.c, we look at the output alarm information:

SPLINT_MSG.C: (in function FUNC_SPLINT_MSG1)
Splint_msg.c:4:6:variable a declared but not used
A variable is declared but never used. Use/*@[email protected]*/in front of
Declaration to suppress message. (Use-varuse to inhibit warning)

SPLINT_MSG.C: (in function FUNC_SPLINT_MSG2)
Splint_msg.c:10:2: Fresh Storage A (type int *) not released before assignment:
A = NULL
A memory leak has been detected. Storage allocated locally is not released
Before the last reference to it is lost. (Use-mustfreefresh to inhibit
Warning
Splint_msg.c:9:37:fresh Storage A created

Finished checking---2 code warnings

Blue font section: gives the function name of the alarm, and prints before the first warning message of the function is reported;

Red font part: The body of the message, the file name, line number, and column number are displayed in front of the body of the warning;

Black Font section: is the detailed information about the suspicious error, including some how to remove the message information;

Green font section: gives extra location information, where the message shows where to apply for this potentially leaking memory.

2. Check Control

Splint provides three ways to check control, respectively. SPLINTRC configuration file, Flags flag, and formatted comment.

flags: Splint supports hundreds of flags to control check and message reporting, use the flag before adding ' + ' or '-', ' + ' flag to turn on this flag, '-' means to turn off this flag, the following example shows the use of the flags flag:

Splint-showcol A.C   //When detecting A.C, the number of columns in the alarm message is not printed
Splint-varuse A.C //When detecting A.C, no variable alarm is used in the alarm message is not printed

. SPLINTRC profile : After installing splint with the source code, the. splintrc file is installed in the home directory, and the. splintrc file has default settings for some flags. The flags flags specified in the command line overwrite the flags in the. splintrc file.

formatting Comments: Formatting comments provide extra information about a type, variable, or function, you can control the flag settings, increase the check effect, all formatting comments start with/*@, @*/end, such as/*@[email protected]*/before the function parameter, Indicates that the parameter may be null, and splint strengthens the detection of the value of the parameter when it is instrumented.

3. Detecting and analyzing content

1. dereference null pointer (null dereferences)

In the UNIX operating system, the dereference null pointer will cause us to produce a segment error when the program runs (segmentation fault), a simple dereference null pointer example is as follows:

1//NULL_DEREFERENCES.C
2 int func_null_dereferences (void)
3 {
4 int* a = NULL;
5 return *a;
6}

Executing the Splint null_dereference.c command will produce the following warning message:

NULL_DEREFERENCE.C: (in function Func_null_dereferences)
Null_dereference.c:5:10:dereference of NULL pointer a: *a
A possibly NULL pointer is dereferenced. Value is either the result of a
function which could return null (in which case, code should check it was not
NULL), or a global, parameter or structure field declared with the null
Qualifier. (Use-nullderef to inhibit warning)
Null_dereference.c:4:11:storage a becomes null

Finished checking---1 code warnin

2. Type (Types)

We often use forced type conversions in programming, converting signed values to unsigned values, large range type values to small range types, and the results of the program running without our expectation.

1//TYPES.C
2 void splint_types (void)
3 {
4 short a = 0;
5 Long B = 32768;
6 a = b;
7 return;
8}

Executing the Splint TYPES.C command will produce the following warning message:

TYPES.C: (in function Splint_types)
Types.c:6:2:assignment of long int to short int:a = b
to ignore type qualifiers in type comparisons use +ignorequals.

Finished checking---1 code warning

3. Memory Management (Management)

In the C language program, nearly half of the bugs are attributed to memory management issues, and memory-related bugs are hard to spot and can cause fatal damage to the program. The problem caused by memory release can be divided into two types:

    • When there are other pointers referenced, free a space
1//memory_management1.c
2 void memory_management1 (void)
3 {
4 int* a = (int*) malloc (sizeof (int));
5 int* B = A;
6 free (a);
7 *b = 0;
8 return;
9}

In the above example, pointer A and B point to the same piece of memory, but after the memory is released, the contents of B point are still assigned, let's see splint
Results of memory_management1.c:

MEMORY_MANAGEMENT1.C: (in function Memory_management1)
Memory_management1.c:7:3:variable B used after being released
Memory is used after it had been released (either by passing as a only param
Or assigning to a only global). (use-usereleased to inhibit warning)
Memory_management1.c:6:7:storage b Released
Memory_management1.c:7:3:dereference of possibly Null pointer B: *b
A possibly NULL pointer is dereferenced. Value is either the result of a
function which could return null (in which case, code should check it was not
NULL), or a global, parameter or structure field declared with the null
Qualifier. (Use-nullderef to inhibit warning)
Memory_management1.c:5:11:storage B may become null

Finished checking---2 code warnings

The results contain two alarms, the first of which indicates that we have used the B pointer, and the memory it points to has been freed, and the second is an alarm to dereference the null pointer.

    • When the last pointer reference is lost, the space it points to is not released
1//memory_management2.c
2 void Memory_management2 (void)
3 {
4 int* a = (int*) malloc (sizeof (int));
5 a = NULL;
6 return;
7}

In this example, the memory is not released, and the unique pointer to it is assigned null, and we look at the results of splint memory_management2.c:

MEMORY_MANAGEMENT2.C: (in function Memory_management2)
Memory_management2.c:5:2:fresh storage A (type int *) not released before assignment:
A = NULL
A memory leak has been detected. Storage allocated locally is not released
Before the last reference to it is lost. (Use-mustfreefresh to inhibit
Warning
Memory_management2.c:4:37:fresh Storage A created

Finished checking---1 code warning

Splint throws an alarm: a type of int* does not release the newly allocated space until A = NULL assignment is made.

4. Cache boundary (buffer Sizes)

Splint will detect the array boundaries, string boundaries, and use the +bounds flag, let's take a look at the following example:

1//bounds1.c
2 void bounds1 (void)
3 {
4 int a[10];
5 a[10] = 0;
6 return;
7}

It is detected using the Splint +bounds bounds1.c command, with the following results:

BOUNDS1.C: (in function Bounds1)
bounds1.c:5:2:likely out-of-bounds store:a[10]
Unable to resolve constraint:
Requires 9 >= 10
needed to satisfy precondition:
Requires Maxset (a @ bounds1.c:5:2) >= 10
A memory write may write to an address beyond the allocated buffer. (Use
-likelyboundswrite to inhibit warning)

Finished checking---1 code warning

The alarm message indicates that the array is out of bounds and accesses the buffer size range beyond our request. Let's look at an example:

1//bounds2.c
2 void Bounds2 (char* str)
3 {
4 char* tmp = getenv ("HOME");
5 if (tmp! = NULL)
6 {
7 strcpy (STR, TMP);
8 }
9 return;
10}

Without a detailed examination of this example, we may not be able to find the implied problem, after executing splint +bounds bounds2.c, the following alarm will be thrown:

BOUNDS2.C: (in function Bounds2)
bounds2.c:7:3:possible out-of-bounds store:strcpy (str, TMP)
Unable to resolve constraint:
Requires Maxset (str @ bounds2.c:7:10) >= maxread (getenv ("HOME") @
BOUNDS2.C:4:14)
needed to satisfy precondition:
Requires Maxset (str @ bounds2.c:7:10) >= maxread (tmp @ bounds2.c:7:15)
Derived from strcpy precondition:requires maxset (<parameter 1>) >=
Maxread (<parameter 2>)
A memory write may write to an address beyond the allocated buffer. (Use
-boundswrite to inhibit warning)

Finished checking---1 code warning

The alarm message prompts us: When using strcpy (STR, TMP) for string copying, there may be an out-of-bounds error because the size of STR may not be sufficient to accommodate the environment variable "HOME" corresponding to the string. The contents of the green font indicate how to eliminate the alarm message.

3. Summary

Here are only 4 kinds of detection splint check: dereference null pointer, type, memory management, cache bounds, in addition, splint also the macro (Macros), function interface (functions Interfaces), control flow, and other content detection , many of the detection flags and formatting comments are not mentioned in this article, please see the Splint User's manual for more detailed information.

Regardless of the function of static program analysis tools such as pc-lint, splint and so on, they also have the omission of the examination of the program, the use of tools can not improve our programming ability, we should learn all kinds of coding errors and code hidden Trouble, with accumulated coding knowledge to stifle the program hidden in the cradle.

C + + code static analysis tool Splint

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.