Chapter 14 Errors Detected by Reactis for C
14.1 Integer Overflows
An integer overflow occurs when an operation produces an integer result which is too large or too small to be represented by the destination type of the operation. When an integer overflow occurs, the course of action taken by Reactis for C depends on the setting for the operation which overflowed: Wrap Over or Error.
14.1.1 Wrapping over
When overflow behavior is set to Wrap Over, Reactis for C emulates the behavior of typical hardware, which is to truncate the most significant bits of the value until the value is small enough to be represented. The effect of wrapping over is different for unsigned and signed integers.
In the case of unsigned integers, wrapping over a value x is typically equal to x mod 2n, where n is the width (in bits) of the container type.
When signed values are wrapped over, the sign bit may
change, producing results whose sign is the opposite of its value
prior to wrapping over.
For example, in most 32-bit environments, adding the
maximum signed int value (
14.1.2 Error diagnosis
When overflow behavior is set to Error, Reactis for C stops execution as close to the statement where the overflow occurred as possible and displays an error dialog. You can hover on variables at this point to see their values and step backward to inspect earlier values if desired.
14.1.3 Controlling overflow behavior
The action taken when integer overflows occur is controlled by the four parameters in the C Code tab of the Global Settings dialog. (See Section 4.3.2 for details on how to set these parameters.) The following operations are controlled by each parameter:
Note that Bit-level operations, such as bitwise-and (
You should also be aware that, according to the C language specification, overflows during unsigned computations are wrapped over. This is different than the specification for signed integer computations, which states that the results for an overflow are undefined. Many C programs are designed to exploit the wrapping over of unsigned values, and setting On unsigned integer overflow to Error for such programs will result in superfluous errors during testing.
14.1.4 Determining the type of an expression
Reactis for C uses C99 rules for determining the type (signed or unsigned)
of integer expressions, which affects when overflows may occur.
For integer constants, the type of the constant is determined by radix of
the constant and the presence of a
The C99 rules for evaluating integer expressions state that values of any type smaller
When two integer values are combined in a binary expression, the width and signedness of the result are determined by two rules:
Operator arguments are converted to the result type before
the expression is evaluated. This means that the expression
14.2 Floating-Point Errors
In C and most other languages,
floating-point calculations which overflow do not trigger an exception,
but instead produce a distinct value which represents positive or
negative infinity (
Reactis for C detects indeterminate and infinite values and will either raise an error,
generate a warning message, or ignore the value, depending on the setting of
When calculation results in NaN (Not-a-Number) or infinity
(see Section 4.3.2).
However, an error or warning is only produced when a the calculation which
Reactis for C also detects subnormal values (also called denormal values or denormalized values). A subnormal value is a floating-point value in which the fractional component has one or more zero leading bits. Subnormal values are used to represent floating-point numbers whose (negative) exponent is less than the smallest possible mantissa value for the floating-point type. Because subnormal values require a loss of precision, Reactis for C provides the option to produce a warning or error for calculations which produce a subnormal result (see Section 4.3.2).
14.3 Memory Errors
Whenever a pointer is used to access memory, Reactis for C performs a safety check to ensure that pointer is valid. There are two steps in the validity check:
Note that it is possible that a program which appears to function correctly actually contains a memory error. For example, consider the function sum shown in Figure 14.3. This function sums the first n+1 element of A, which will include 1 element past the end of the array when n equals the number of elements in A. If the element which follows the end of A happens to always be zero, sum will function “correctly” in the sense that its return value is equal to what the programmer intended. At some point the future, however, a change to the program may cause the invalid memory access to return a non-zero value, which will cause the value returned by sum to be incorrect. Even worse, there may be rare runtime conditions under which the memory access returns a non-zero value, causing intermittent program malfunctions which are difficult to reproduce and diagnose. Hence it is best to detect and fix such errors even though they may not seem to be presently causing a problem.
14.3.1 Uninitialized Memory
In C, variables which are allocated in static memory (which includes all variables declared with the static keyword plus all variables declared outside the body of a function) are initialized to zero when there is no initial value given in the source code. Variables declared inside the body of a function without the static keyword, on the other hand, have no default initializer, and if they are not initialized in the source code will receive an value which is undefined by the C standard (which in practice is whatever value happens to be stored in the memory location where the variable is allocated when the function is called). Reading the contents of such a variable prior to the first write is another difficult to diagnose error which afflicts programs written in C.
Similarly, memory which is dynamically-allocated by malloc() is uninitialized, and it is the responsibility of the caller to initialize the memory before reading from it.
Reactis for C keeps tracks of which memory locations have been initialized and will raise an error when an attempt to read from uninitialized memory occurs.
14.3.2 Invalid Pointer Creation
Reactis for C can produce an error or warning whenever a pointer expression produces an invalid pointer. This can help determine the source of a memory error. However, there are cases where invalid pointers are produced which are never dereferenced, such as the following program fragment:
During the last iteration of the above loop, the pointers
14.4 Other Runtime Errors
In addition to memory errors and overflows, Reactis for C also detects the errors listed below. The C standard states that the results of these operations are undefined.