Variadic function (a function whose last formal parameter is an ellipsis) takes an object of a class type as an actual argument that is part of an ellipsis, which may indicate a logical error. 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:
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.
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:
//-V:MySuperPrint:510
It is possible to read about multiple warning suppression in details in section "Suppression of false alarms".
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);
This diagnostic is classified as:
|
You can look at examples of errors detected by the V510 diagnostic. |