Our website uses cookies to enhance your browsing experience.
Accept
to the top
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam

Webinar: Evaluation - 05.12

>
>
>
V576. Incorrect format. Consider checki…
menu mobile close menu
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Micro-Optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C++)
OWASP errors (C#)
Problems related to code analyzer
Additional information
toggle menu Contents

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

Dec 09 2014

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 the '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 example:

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");
        exit(1);
    }
    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 the '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);

Wide character strings

Visual Studio has one displeasing feature when it interprets the string format in a non-standard way to print wide characters. Therefore, the analyzer can diagnose errors in code like the following sample:

const wchar_t *p = L"abcdef";
wprintf(L"%S", p);

In Visual C++, '%S' is meant to be used to print a string of the 'const char *' type, so from its viewpoint, the correct version of the code above should look like this:

wprintf(L"%s", p);

Starting with Visual Studio 2015, the developers offer a solution to this issue for the sake of compatibility. To make your code compatible with ISO C (C99), you need to specify the _CRT_STDIO_ISO_WIDE_SPECIFIERS macro for the preprocessor.

In that case, the code:

const wchar_t *p = L"abcdef";
wprintf(L"%S", p);

will be treated as correct.

PVS-Studio knows about the '_CRT_STDIO_ISO_WIDE_SPECIFIERS' macro and takes it into account when performing the analysis.

By the way, if you have the ISO C compatibility mode enabled (i.e. declared the '_CRT_STDIO_ISO_WIDE_SPECIFIERS' macro), you can restore the old-type conversion in certain places by using the '%Ts' format specifier.

This story with wide characters is quite complicated and is outside the scope of this documentation. To figure it all out, see the following resources:

Additional diagnostic setup

Use custom annotations to specify the names of user-declared functions for which the format check should be performed. You can read more about this here.

Additional references:

This diagnostic is classified as:

You can look at examples of errors detected by the V576 diagnostic.