Handling "incompatibily" overloaded names in Cppcheck - c++

I'm stuck with a "conflict" between with AnsiStrings sprintfmember function and Cppcheck's built-insprintf` knowledge.
In cases like this,
const char* name = "X";
int version = 1;
return AnsiString().sprintf("%s.H%02d", name, version); // <-- HERE
I'm getting this warning in the Cppcheck GUI
Id: wrongPrintfScanfArgNum
Summary: sprintf format string requires 0 parameters but 1 is given.
Message: sprintf format string requires 0 parameters but 1 is given.
which shows that Cppcheck is talking about the sprintf function, but I'm using a member function of the VCL class AnsiString with the same name.
As to get rid of this false positive, I could use
an inline suppression: // cppcheck-suppress wrongPrintfScanfArgNum
an intermediate variable: AnsiString result; result.printf(...); return result;
the sprintf function, which means handle the buffer space manually
But all these options work local, and make the code harder to read/maintain.
How can I teach Cppcheck to differentiate between overloaded names?
Edits:
I wrote override, but meant overloading, I corrected that in the current text.
added literal initialization of variables, which is important for name

Interesting.
Yes I agree this should be reported in http://trac.cppcheck.net. Looks like bugs.
I can see 2 bugs.
The AST does not show proper type information for the 'AnsiString()' even when I add a AnsiString class.
The Library should not match sprintf in that code. It is clear that some method is called.

It really is a bug.[1] Cppcheck 1.75 is smart in checking format strings, but obviously only in some cases, one of them is the second parameter of every function called printf, so the problem has nothing to do with AnsiString::sprintf but with every alternate implementation.
[1]
#7726 (False positive: format string checked for every function called 'sprintf') – Cppcheck

Related

Pass CString to fprintf

I have ran the code analyzer in visual studio on a large code base and i got about a billion of this error:
warning C6284: Object passed as parameter '3' when string is required in call to 'fprintf'
According to http://msdn.microsoft.com/en-us/library/ta308ywy.aspx "This defect might produce incorrect output or crashes." My colleague however states that we can just ignore all these errors without any problems. So one of my questions is do we need to do anything about this or can we just leave it as is?
If these errors need to be solved what is the nicest approach to solve it?
Would it work to do like this:
static_cast<const char*>(someCString)
Is there a better or more correct approach for this?
The following lines generate this warning:
CString str;
fprintf(pFile, "text %s", str);
I'm assuming that you're passing a Microsoft "CString" object to a printf()-family function where the corresponding format specifier is %s. If I'm right, then your answer is here: How can CString be passed to format string %s? (in short, your code is OK).
It seems that originally an implementation detail allowed CString to be passed directly to printf(), and later it was made part of the contract. So you're good to go as far as your program being correct, but if you want to avoid the static analysis warning, you may indeed need to use the static_cast to a char pointer. I'm not sure it's worth it here...maybe there's some other way to make these tools place nice together, since they're all from Microsoft.
Following the MSDN suggestions in C6284, you may cast the warnings away. Using C++ casts will be the most maintainable option to do this. Your example above would change to
fprintf(pFile, "text %s", static_cast<const TCHAR*>(str));
or, just another spelling of the same, to
fprintf(pFile, "text %s", static_cast<LPCTSTR>(str));
The most convincing option (100% cast-free, see Edits section) is
fprintf(pFile, "text %s", str.GetString());
Of course, following any of these change patterns will be a first porting step, and if nothing indicates a need for it, this may be harmful (not only for your team atmosphere).
Edits: (according to the comment of xMRi)
1) I added const because the argument is read-only for fprintf
2) notes to the cast-free solution CSimpleStringT::GetString: the CSimpleStringT class template is used for the definition of CStringT which again is used to typedef the class CString used in the original question
3) reworked answer to remove noise.
4) reduced the intro about the casting option
Technically speaking it is ok because the c-string is stored in such a way in CString that you can use it as stated but it is not good rely on how CString is implemented to do a shortcut. printf is a C-runtime function and knows nothing about C++ objects but here one is relying on an that the string is stored first in the CString - an implementation detail.
If I recall correctly originally CString could not be used that way and one had to cast the CString to a c-string to print it out but in later versions MS changed the implementation to allow for it to be treated as a c-string.
Another breaking issue is UNICODE, it will definitely not work if you one day decide to compile the program with UNICODE character set since even if you changed all string formatters to %ld, embedded 0s will sometimes prevent the string from being printed.
The actual problem is rather why are you using printf instead of C++ to print/write files?

Tool to Verify Format Strings in C/C++ source

I have updated the contents and arguments of printf style format strings in a large C/C++ code base. The code compiles ok but it is hard to actually get those errors and verify that my changes were right.
Is there a tool/compiler option that can validate the format strings for having the right no. of arguments. It would be nice if it doesn't try to compile the whole thing because then the dependencies etc must be present in the expected places.
I could write a quick script but I could reuse something that already exists and handles the corner cases too.
Something like :-
% cat test.c
#include <iostream>
#include "dependency2.h"
int main()
{
function2(log, "You encountered a common error %s: %d", error)
}
% somenicetool test.c
5: too few arguments
I tried clang but the first error it gives is this :-
% clang -fsyntax-only test.c
#include "dependency2.h"
^
file not found
1 error generated
If using gcc and --Wformat, and you have your own functions, you will need to use the __attribute__(format, printf, format_argno, first_var_arg) after the function.
For example:
void log_print(FILE *logfile, int level, const char *format, ...)
__attribute__(format, printf, 3, 4);
gcc also understands "scanf", "strfmon" and "strftime" format specifications, just replace "printf" with whatever suits your function.
With gcc, you can use the --Wformat option:
Check calls to printf and scanf, etc., to make sure that the arguments
supplied have types appropriate to the format string specified, and
that the conversions specified in the format string make sense. This
includes standard functions, and others specified by format attributes
(see Function Attributes), in the printf, scanf, strftime and strfmon
(an X/Open extension, not in the C standard) families (or other
target-specific families).
See the gcc documentation for more details.
Edit: Looking at this more carefully, it looks like you want to check calls to your own functions which possibly forward the calls to printf and friends. You probably have to decorate your function with the format function attribute in order to get the warnings from gcc.
I think CPPCheck picks up those, and plenty, plenty more...
Edit: Hmm. I have a feeling it only works for standard library functions, and doesn't understand the 'Function Attributes' you can use to tell GCC that your 'own' functions use format strings.
One thing to remember about the __attribute__ ((format (printf, n, m))) solution: if your function is a non-static member method of a class, you have to add 1 to both n and m since it's compiled as a simple function with the this pointer as the actual first parameter.
Looks like cppcheck can do it! See manual, section "3.1.4 Format string".
Also, ReSharper can do it.

Name variable Lua

I have the following code in Lua:
ABC:
test (X)
The test function is implemented in C + +. My problem is this: I need to know what the variable name passed as parameter (in this case X). In C + + only have access to the value of this variable, but I must know her name.
Help please
Functions are not passed variables; they are passed values. Variables are just locations that store values.
When you say X somewhere in your Lua code, that means to get the value from the variable X (note: it's actually more complicated than that, but I won't get into that here).
So when you say test(X), you're saying, "Get the value from the variable X and pass that value as the first parameter to the function test."
What it seems like you want to do is change the contents of X, right? You want to have the test function modify X in some way. Well, you can't really do that directly in Lua. Nor should you.
See, in Lua, you can return values from functions. And you can return multiple values. Even from C++ code, you can return multiple values. So whatever it is you wanted to store in X can just be returned:
X = test(X)
This way, the caller of the function decides what to do with the value, not the function itself. If the caller wants to modify the variable, that's fine. If the caller wants to stick it somewhere else, that's also fine. Your function should not care one way or the other.
Also, this allows the user to do things like test(5). Here, there is no variable; you just pass a value directly. That's one reason why functions cannot modify the "variable" that is passed; because it doesn't have to be a variable. Only values are passed, so the user could simply pass a literal value rather than one stored in a variable.
In short: you can't do it, and you shouldn't want to.
The correct answer is that Lua doesn't really support this, but there is the debug interface. See this question for the solution you're looking for. If you can't get a call to debug to work directly from C++, then wrap your function call with a Lua function that first extracts the debug results and then calls your C++ function.
If what you're after is a string representation of the argument, then you're kind of stuck in lua.
I'm thinking something like in C:
assert( x==y );
Which generates a nice message on failure. In C this is done through macros.
Something like this (untested and probably broken).
#define assert(X) if(!(X)) { printf("ASSERION FAILED: %s\n", #X ); abort(); }
Here #X means the string form of the arguments. In the example above that is "x==y". Note that this is subtly different from a variable name - its just the string used in the parser when expanding the macro.
Unfortunately there's no such corresponding functionality in lua. For my lua testing libraries I end up passing the stringified version as part of the expression, so in lua my code looks something like this:
assert( x==y, "x==y")
There may be ways to make this work as assert("x==y") using some kind of string evaluation and closure mechanism, but it seemed to tricky to be worth doing to me.
EDIT:
While this doesn't appear to be possible in pure lua, there's a patched version that does seem to support macros: http://lua-users.org/wiki/LuaMacros . They even have an example of a nicer assert.

Variable arguments weirdness

Ok, so this piece of code works fine in the Debug but not in Release build.
int AddString(LPCTSTR lpszString, ...)
{
RArray<LPCTSTR> strings;
va_list args;
va_start(args, lpszString);
do
{
strings.Add(lpszString);
} while (lpszString = va_arg(args, LPCTSTR));
va_end(args);
// ... rest of code ...
}
It seems in Release, va_arg just returns an extra value containing rubbish. So if I pass on 3 parameters: I fetch 3 in Debug and miraculously 4 in Release... How is this possible? Using VS2010 btw.
(RArray is just a simple template class comparable to MFC's CArray, does not influence results)
Thanks!
Edit: I call it like this
AddString(_T("Hello, world!"), _T("Hallo, wereld!"), _T("Hallo, Welt!"));
You're doing it the wrong way and you're just lucky with the debug build.
Notice that va_arg does not determine either whether the retrieved argument
is the last argument passed to the function (or even if it is an element
past the end of that list). The function should be designed in such a way
that the amount of parameters can be inferred in some way by the values of
either the named parameters or the additional arguments already read.
Supply either the length of the list in an integer or pass a NULL at the end of the list.
You're not supplying the final NULL argument your function expects. You have to do this yourself at the point where you call AddString:
AddString(_T("Hello, world!"), _T("Hallo, wereld!"), _T("Hallo, Welt!"), NULL);
It is likely that the debug build zeros out some memory that the release build doesn't. This could explain why your code works in debug but not in release.
Also, you might want to convert the do {} while (...) loop into while (...) {}, to make sure your code doesn't malfunction if no optional arguments are given.
va_arg does not offer any guarantee to return 0 after last real argument.
If you're going to use the C style variable arguments, then you need to establish some way of determining the number of arguments, e.g. a count or a terminating zero.
For example, printf determines the arguments from the format specification argument.
In C++ you can often, instead, use chained calls, such as the operator<< calls used for standard iostreams.
The simple, basic idea is that the operator or function returns a reference to the object that it is called on, so that further operator or function calls can be appended.
Cheers,

c++ va_arg typecast issue

All,
I am writing a small c++ app and have been stumped by this issue. Is there a way to create (and later catch ) the error while accessing element from va_list macro using va_arg if element type is not expected. Eg:-
count=va_arg(argp,int);
if (count <= 0 || count > 30)
{
reportParamError(); return;
}
Now, if I am passing a typedef instead of int, I get garbage value on MS compiler but 95% of time count gets value 0 on gcc (on 64 bit sles10 sys). Is there a way I can enforce some typechecking, so that I get an error that can be caught in a catch block?
Any ideas on this would be very helpful to me. Or is there a better way to do this. The function prototype is:-
void process(App_Context * pActx, ...)
The function is called as
process(pAtctx,3,type1,type2,type3);
It is essential for pActx to be passed as 1st parameter and hence cannot pass count as 1st parameter.
Update-1
Ok, this sounds strange but nargs does not seem to part of va_list on sles10 gcc. I had to put in
#ifdef _WIN32
tempCount=va_arg(argp,int)
#endif
After using this, parameters following nargs do not get garbage values. However, this introduces compiler/platform based #ifdefs....Thanks Chris and Kristopher
If you know a count will always be passed as the second argument, then you could always change the signature to this:
void process(App_Context * pActx, int count, ...)
If that's not an option, then there is really no way to catch it. That's just how the variable-argument-list stuff works: there is no way for the callee to know what arguments are being passed, other than whatever information the caller passes.
If you look into how the va_arg macro and related macros are implemented, you may be able to figure out how to inspect all the stuff on the stack. However, this would not be portable, and it is not recommended except as a debugging aid.
You also might want to look into alternatives to variable-arguments, like function overloading, templates, or passing a vector or list of arguments.
No, there is no way. varargs doesn't provide any way to check the types of parameters passed in. You must only read them with the correct type which means that you need another way of communicating type information.
You are likely to be better off avoiding varargs functionality unless you really need it. It's only really a C++ feature for the sake of legacy functions such as printf and friends.