V510. The 'Foo' function is not expected to receive class-type variable as 'N' actual argument.

There are functions in whose description it is impossible to specify the number and types of all the acceptable parameters. In this case, the list of formal arguments ends with the ellipsis (...) that means: "and perhaps some more arguments". Here is an example of an ellipsis function: "int printf(const char* ...);". Only POD-types can serve as actual arguments for ellipsis.

POD is an abbreviation for "Plain Old Data", i.e. "Plain data in C style". The following types and structures refer to POD-types:

  • all the built-in arithmetic types (including wchar_t and bool);
  • types defined with the enum key word;
  • pointers;
  • POD-structures (struct or class) and POD-unions that meet the following requirements:
    • do not contain user constructors, destructor or copying assignment operator;
    • do not have base classes;
    • do not contain virtual functions;
    • do not contain protected or private non-static data members;
    • do not contain non-static data members of non-POD-types (or arrays of such types) and references.

If a class object is passed to an ellipsis function, this almost always indicates an error in program. The V510 rule helps detect incorrect code of the following kind:

wchar_t buf[100];
std::wstring ws(L"12345");
swprintf(buf, L"%s", ws);

The object's contents are saved into the stack instead of the pointer to the string. This code will cause generating "abracadabra" in the buffer or a program crash.

The correct version of the code must look this way:

wchar_t buf[100];
std::wstring ws(L"12345");
swprintf(buf, L"%s", ws.c_str());

Since you might pass anything you like into functions with a variable number of arguments, almost all the books on C++ programming do not recommend using them. They suggest employing safe mechanisms instead, for instance, boost::format.

Note about C++11

In new standard, it is said that:

C++11 5.2.2/7: Passing a potentially-evaluated argument of class type having a non-trivial copy constructor, a non-trivial move constructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics.

Thus, it is possible to pass into function' ellipsis "more various kinds" of objects. However, we decided not to change anything in this rule. In 99% of cases transferring a complex class as an argument is a misprint or another kind of error. This code should be reviewed. In case of inconvenience caused by large amount of false alarms related to this warning, it is possible to mark these functions to suppress it massively. An example:


It is possible to read about multiple warning suppression in details in section "Suppression of false alarms".

Note one specific thing about using the CString class from the MFC library

We must see an error similar to the one mentioned above in the following code:

CString s;
CString arg(L"OK");
s.Format(L"Test CString: %s\n", arg);

The correct version of the code must look in the following way:

s.Format(L"Test CString: %s\n", arg.GetString());

Or, as MSDN suggests [1], you may use the explicit cast operator LPCTSTR implemented in the CString class to get a pointer to the string. Here is a sample of correct code from MSDN:

CString kindOfFruit = "bananas";
int howmany = 25;
printf("You have %d %s\n", howmany, (LPCTSTR)kindOfFruit);

However, the first version "s.Format(L"Test CString: %s\n", arg);" is actually correct as well like the others. This topic is discussed in detail in the article "Big Brother helps you" [2].

The MFC developers implemented the CString class in a special way so that you could pass it into functions of the printf and Format types. It is done rather intricately and if you want to make it out, study implementation of the CStringT class in the source codes.

So, the analyzer makes an exception for the CStringT type and considers the following code correct:

CString s;
CString arg(L"OK");
s.Format(L"Test CString: %s\n", arg);

Related materials

Do you make errors in the code?

Check your code
with PVS-Studio

Static code analysis
for C, C++ and C#

goto PVS-Studio;