Issues in real programs - what errors are not there in the world

10.12.2009 Andrey Karpov

When testing the analyzer PVS-Studio on one of the projects we found an interesting error. This error does not refer to the topic of 64-bits although its consequences are diagnosed as 64-bit problems. But this error attracts attention due to its unusual character and we decided to describe it in the blog.

Here is the code of a program that, as the author had intended, was to print the value of the matrix items into the internal structure.

Matrix3 m;
TextOutput &t = ...;
...
t.printf("%10.5f, %10.5f, %10.5f,\n%10.5f,"
  "%10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f)",
  m[0, 0], m[0, 1], m[0, 2],
  m[1, 0], m[1, 1], m[1, 2],
  m[2, 0], m[2, 1], m[2, 2]);

Of course, this code is incorrect although compiles well. It seems that the author, while developing the code, had been distracted by work on a project in a different language and therefore confused the syntaxes. As a result, the expressions of the type "1, 2″ have the value of the subexpression after the last comma according to C++ language rules. I.e. the expression "1, 2″ equals 2.

As a result, the given code is equivalent to this:

Matrix3 m;
TextOutput& t = ...;
...
t.printf("%10.5f, %10.5f, %10.5f,\n%10.5f,"
  "%10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f)",
  m[0], m[1], m[2],
  m[0], m[1], m[2],
  m[0], m[1], m[2]);

Matrix3 class has an overloaded operator [] that returns the pointer to float type:

inline const float* operator[] (int iRow) const;

Of course, it does not matter at all to the function printf what to take as arguments: float or float*. The project compiles with the warning level /W3 and the compiler keeps silent when it comes to these suspicious constructs. To make Visual C++ generate the warning you should raise the warning level up to /W4. Then you will see the diagnostic warning "warning C4709: comma operator within array index expression".

PVS-Studio analyzer does not like this code too but due to a different reason. The expression "m[0]" has "float *" type, i.e. memsize-type and is an argument for the function with a variable number of arguments. The analyzer considers that this code can potentially contain errors and generates the diagnostic warning "error V111: Call function 'printf' with variable number of arguments. Second argument has memsize type."