Example: Data Race

The example below shows a basic OpenMP* parallel for loop. The #pragma omp indicates that the iterations of this loop are intended to run in parallel. The reduction clause on line 7 causes the variable "sum" to be replaced in the body of the loop with a per-thread temporary. The values of all these temporaries are added together and assigned to the outer variable named sum at the end of the loop.

The loop iterations always run in order in serial mode. If the same memory location is written on one iteration and read on another, there is no guarantee in parallel mode the read and write will happen in the same order as they did in serial mode. If the same memory location is written in two iterations, then the final value depends on which writes last. These usage patterns are called loop-carried data dependencies. Their presence implies that the order of execution of independent threads can affect the meaning of the application - an error condition called a data race.

The example below contains two possible data dependencies related to the variable b. On line 9, the a[i]-th element of b is written, and on line 10, the i-th element of b is read. Depending on the values in the array a, this might mean that the same array element is read in one iteration and written in another. It could also mean that the same value is written in two iterations on line 9. Note that the variable "sum" would create an unconditional loop-carried data dependency, but the reduction clause removes this problem because each thread has its own copy of sum.

In this particular case, static analysis cannot know for sure whether a data race actually exists or not. For example, if a[i] were equal to i (or equal to zero) for all values of i between 1 and 99, then no data race would exist. Therefore these issues are reported as possible data race errors.

This same kind of parallel application (with the same data races) can be coded using Intel® Cilk™ Plus methodology as shown below. Here the reduction clause is replaced by a hyperobject. The same error would also be detected during static analysis.

Example: Tainted Variable Usage

Many security issues are caused by failure to adequately screen user input. Static analysis regards values that come into the application from outside (such as from input statements or command line parameters) as suspicious or tainted. Static analysis flags cases where tainted data is used in a dangerous way without prior examination. Here is an example:

Note that static analysis cannot determine whether a specific check is adequate to make a tainted value safe. Just about any kind of check removes the taint and causes static analysis to allow it to be used freely. For example, this application really is no better than the one above, but it would not be flagged with a tainted variable error. A better check would be if (upper < 1000).