V576. Incorrect format. Consider checking the N actual argument of the 'Foo' function


The analyzer has detected a potential issue with the application of formatted output functions. (printf, sprintf, wprintf etc.) The formatting string doesn't correspond with actual arguments passed into the function. Let's review a simple example:

int A = 10;
double B = 20.0;
printf("%i %i\n", A, B);

According to the formatting string the 'printf' function is expecting two actual arguments of the 'int' type. However the second argument's value is of the 'double' type. Such an inconsistency leads to undefined behavior of a program. For example, it can lead to the output of senseless values.

The correct version:

int A = 10;
double B = 20.0;
printf("%i %f\n", A, B);

It's possible to cite countless examples of 'printf' function's incorrect use. Let's review some of the typical examples that are the most frequently encountered in applications.

Address printout.

The value of a pointer is quite commonly printed using these lines:

int *ptr = new int[100];
printf("0x%0.8X\n", ptr);

This source code is invalid because it will function properly only on systems which have their pointer size equal to size of 'int' type. For example In Win64 this code will print only the low-order part of the 'ptr' pointer. The correct version:

int *ptr = new int[100];
printf("0x%p\n", ptr);

The analyzer has detected the potential issue with an odd value being passed as the function's actual argument.

Unused arguments.

You can often encounter function calls in which some of these function's arguments are being unused.

For instance:

int nDOW;
#define KEY_ENABLED "Enabled"
wsprintf(cDowKey, L"EnableDOW%d", nDOW, KEY_ENABLED);

It is obvious that the KEY_ENABLED parameter is unnecessary here or the source code should look like this:

wsprintf(cDowKey, L"EnableDOW%d%s", nDOW, KEY_ENABLED);

Insufficient number of arguments.

A little more dangerous is the situation in which the number of arguments passed to the function is less than necessary. This can easily lead to the memory access error, buffer overflow or senseless printout. Let's review an example of memory allocation function taken from a real life application:

char* salloc(register int nbytes)
    register char* p;
    p = (char*) malloc((unsigned)nbytes);
    if (p == (char *)NULL)
        fprintf(stderr, "%s: out of memory\n");
    return (p);

If 'malloc' returns NULL, the program will not be able to report the shortage of memory and to be terminated correctly. It instead will be terminated emergently and it will output the senseless text. In any case such a behavior will complicate analysis of the program's inoperability.

Confusion with signed/unsigned

Developers often employ the character printing specificator ('%i' for example) to output the variables of unsigned type. And vice versa. This error usually is not critical and is encountered so often than it has a low priority in analyzer. In many cases such source code works flawlessly and fails only with large or negative values. Let us examine the code which is not correct, but successfully works:

int A = 10;
printf("A = %u\n", A);
for (unsigned i = 0; i != 5; ++i)
  printf("i = %d\n", i);

Although there is an inconsistency here, this code outputs correct values in practice. Of course it's better not to do this and to write correctly:

int A = 10;
printf("A = %d\n", A);
for (unsigned i = 0; i != 5; ++i)
  printf("i = %u\n", i);

The error will manifest itself in case there are large or negative values in the program. An Example:

int A = -1;
printf("A = %u", A);

Instead of "A=-1" string the program will print "A=4294967295". The correct version:

printf("A = %i", A);

Additional reference:

You can look at examples of errors from real projects which were detected by this diagnostic message.