Trouble understanding __attribute__ tag - c++

extern "C" int asnprintf (char **ret, size_t max_sz, const char *format, ...)
__attribute__ ((format (printf, 3, 4)));
Reading the source code of nmap I came accross this function declaration and I am having troubles understanding it.
Here is what this webpage says about it:
Based on
__attribute__((format(printf, m, n)));
The (m) is the number of the "format string" parameter, and (n) is the number of the first variadic parameter.
I don't understand what is he refering to when saying "format string"; are they just the arguments which affects the behaviour of the function?
Also, what is the number of the first variadic parameter? In all the examples I have seen it is always one more than m, is this always true? Could you give a practical example where is not?
Thanks.

extern "C" int asnprintf (char **ret, size_t max_sz, const char *format, ...)
^1 ^2 ^3 ^4
I don't understand what is he refering to when saying "format string"; are they just the arguments which affects the behaviour of the function?
The format string is the one you generally find in printf for example, like "%0.3f %s" ecc. and of course the function will act accordingly.
Also, what is the number of the first variadic parameter? In all the examples I have seen it is always one more than m, is this always true? Could you give a practical example where is not?
In that case, m = 3 and n = 4, but it need not be so. Let's say you have
int blablabla(const void *const data, const char *format, int data, ...)
then m = 2 and n = 4.

The answer is in the gcc manual:
The format attribute specifies that a function takes printf, scanf,
strftime or strfmon style arguments which should be type-checked
against a format string.
format (archetype, string-index, first-to-check)
The parameter archetype determines how the format string is
interpreted, and should be printf, scanf, strftime or strfmon. (You
can also use printf, scanf, strftime or strfmon.) The
parameter string-index specifies which argument is the format string
argument (starting from 1), while first-to-check is the number of the
first argument to check against the format string. For functions where
the arguments are not available to be checked (such as vprintf),
specify the third parameter as zero. In this case the compiler only
checks the format string for consistency. For strftime formats, the
third parameter is required to be zero. Since non-static C++ methods
have an implicit this argument, the arguments of such methods should
be counted from two, not one, when giving values for string-index and
first-to-check.

Related

How to make variable to be a literal string

Code as below:
FILE *sfp;
....
void test(char *s, ...)
{
va_list ap;
va_start(ap, s);
vfprintf(sfp, s, ap);
fflush(sfp);
va_end(ap);
}
below compile error reported:
error: format string is not a string literal [-Werror,-Wformat-nonliteral]
vfprintf(sfp, s, ap);
How to fix this error?
A variable is never a string literal. A string literal is a sequence of characters surrounded by double quote marks (i.e. "foo").
The purpose of that warning is to warn you that the compiler cannot confirm that the types of the parameters given to vfptrintf match the format string. To get rid of that warning, you will need to either
Pass a literal format string to vfprintf (i.e. vfprintf(sfp, "%d\n", ap))
Disable (or rather, don't enable) that warning and accept that the compiler cannot warn you if your arguments don't match the format specifier.
Add the format attribute to your function declaration (thanks to #chris in the comments):
i.e.
__attribute__((format(printf, 2, 3)))
void test(FILE* sfp, const char *s, ...)
{
//...
}
Or with the standardized C++11 attribute syntax:
[[gnu::format(printf, 2, 3)]]
void test(FILE* sfp, const char *s, ...)
{
//...
}
Note that that last option is not a standard C++ attribute, and therefore will not work on all compilers. You may need something else to appease MSVC for example. By the standard, compilers should ignore unknown attributes if you use the C++11 syntax, but they may still emit a warning about it, putting you right back in the same situation you're in now.
You will also still provoke a warning if test is called with a second argument that is not itself a string literal.
As a side note, it doesn't look like clang can check the argument types of the va_list printf functions anyway, so -Wformat-nonliteral isn't actually helpful in this case. GCC does not emit this warning, likely for that exact reason.

how to determine how many arguments would be needed to fulfill fprint formatted string?

I mean strings like "(%d%%%d) some text %s , %d%% %x %o %#x %#o \n". The printf family of functions somehow know how many args they would need from this string so separate argument for it is not needed. Is this functionality provided in c/c++ in terms of a separate function so I could write my own printf-like functions ? (yes I put these percents intentionally to accent how complicated it could get, so it is not simple counting of percent characters)
The problem with printf family is that it is not safe, and it doesn't really know or care how many format elements are there in string or in argument list.
printf family uses something called "variadic functions"; only one parameter is named (format string) and others are taken from the stack, without respecting their type or size - their type is deduced from format string, which makes it type-unsafe, and finds how many arguments to use by iterating over the string and finding all formatting specifiers, which makes it argument-number-unsafe. You can write variadic functions; syntax is
void foo(...);
and later you can use those macros and types, although if you are using C++, you should use C++11's variadic templates instead of C variadic functions, as variadic templates are type safe - you don't loose type information anywhere, and with universal references (but not quite thanks them) they are more powerful than variadic functions.
No, there is no standard library function for parsing printf-style format strings. If you want to write your own string formatting function, then I strongly recommend against following the printf example. It's inherently unsafe for the reasons mentioned in the others answers. It also has problems with localization since word order changes in some languages. Personally, I would write a type-safe function using templates and copying the .NET style of format strings. (Actually, I did do that--it's a lot of work but also fun.)
the printf family of functions only knows about one parameter, the first one...
It basically scans the string and each time it encounters a format specifier that it understands it pulls then next argument of that size from the argument list... this is an easily corruptible behavior.
imagine:
printf("%i",someInt); // fine
printf("%i",someLong); // depending on endianness and sized
// of those types could be the high or low 32 bits(probably)
printf("%i %i",someInt); // depending on abi could crash, read a int sized chunk
// of stack, or a register that would correspond to that
// parameter.
so inherently not safe..
you should pay attention to warnings and when writing portable code do things like:
size_t t = 5; //can be 32 or 64 bit depending on arch.
printf("%ull",(unsigned long long)t);
Edit. I guess I only half answered the question...
you can define your own variadic functions, the following adds count number of params and returns the result.
int sumList(int count, ...);
int main(int argc, const char * argv[])
{
printf("the answer is: %i",sumList(4,1,2,3,4));
return 0;
}
int sumList(int count, ...)
{
va_list args;
va_start(args, count);
int sum = 0;
for (int i = 0; i<count; i++) {
sum += va_arg(args, int);
}
va_end(args);
return sum;
}

How to determine if va_list is empty

I have been reading that some compilers support va_list with macros and users were able to overload the functionality with other macros in order to count the va_list.
With visual studio, is there a way to determine if the va_list is empty (aka count==0)? Basically I would like to know this condition:
extern void Foo(const char* psz, ...);
void Test()
{
Foo("My String"); // No params were passed
}
My initial thought was to do something like this:
va_list vaStart;
va_list vaEnd;
va_start(vaStart, psz);
va_end(vaEnd);
if (vaStart == vaEnd) ...
The problem is that va_end only sets the param to null.
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap) ( ap = (va_list)0 )
I was thinking of maybe incorporating a terminator but I would want it to be hidden from the caller so that existing code doesnt need to be changed.
There is no way to tell how many arguments are passed through ..., nor what type they are. Variadic function parameters can only be used if you have some other way (e.g. a printf-style format string) to tell the function what to expect; and even then there is no way to validate the arguments.
C++11 provides type-safe variadic templates. I don't know whether your compiler supports these, or whether they would be appropriate for your problem.
I realize this question is fairly old, but I thought it might be helpful to flesh it out a bit. As Mike Seymour answered quite correctly, there is no absolutely reliable way to determine the number of arguments in a va_list. That's why the conventional way to define a variadic function is to include a parameter that has that information, like so: void func(const char *str, int count, ...);, which defines a contract your callers are supposed to abide by.
EDIT: The standard (7.16.1.1.3) is actually silent on the value returned by va_arg(vl, type) for any call past the end of the variable argument list. The most common case for most types is typed-zero. However, CAVEAT EMPTOR - it doesn't have to be.
The value returned from va_arg(vl, type) when there are no more arguments is a typed-zero value. For numeric types, it is 0. For pointers, it is a NULL pointer. For structs, it is a struct with all fields zeroed. If you elect to copy the va_list and try to count the copy, like so:
void func(const char *str, ...) {
va_list vl;
va_list vc;
int x;
int count;
count = 0;
va_start(vl, str);
va_copy(vc, vl);
do {
x = va_arg(vc, int);
if (x == 0) break;
count++;
} while (1)
va_end(vc);
.
.
. // do something, or something else,
. // based on the number of args in the list
.
va_end(vl);
You would have to make the assumption that the caller would abide by the contract not to pass a NULL or zero value in the list. Either way, you have to understand that the caller of a variadic function is responsible for abiding by the stated contract. So write your function, publish the contract, and sleep easy.
I am aware that my answer isn't an "orthodox" answer, however due to the limitation of the va_list macro, I found the following solution to work. We can look at a va_list as an array of chars, and even better, a null terminated one, so you can try
va_list argptr;
if(strcmp(argptr,""))
{
// not empty
}
else
{
// empty
}
I tried that and it worked for me.
I used Visual Studio 2013 Ultimate. The project type is Win32 Console Application. No compilation errors.

printf with std::string?

My understanding is that string is a member of the std namespace, so why does the following occur?
#include <iostream>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString);
cin.get();
return 0;
}
Each time the program runs, myString prints a seemingly random string of 3 characters, such as in the output above.
C++23 Update
We now finally have std::print as a way to use std::format for output directly:
#include <print>
#include <string>
int main() {
// ...
std::print("Follow this command: {}", myString);
// ...
}
This combines the best of both approaches.
Original Answer
It's compiling because printf isn't type safe, since it uses variable arguments in the C sense1. printf has no option for std::string, only a C-style string. Using something else in place of what it expects definitely won't give you the results you want. It's actually undefined behaviour, so anything at all could happen.
The easiest way to fix this, since you're using C++, is printing it normally with std::cout, since std::string supports that through operator overloading:
std::cout << "Follow this command: " << myString;
If, for some reason, you need to extract the C-style string, you can use the c_str() method of std::string to get a const char * that is null-terminated. Using your example:
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString.c_str()); //note the use of c_str
cin.get();
return 0;
}
If you want a function that is like printf, but type safe, look into variadic templates (C++11, supported on all major compilers as of MSVC12). You can find an example of one here. There's nothing I know of implemented like that in the standard library, but there might be in Boost, specifically boost::format.
[1]: This means that you can pass any number of arguments, but the function relies on you to tell it the number and types of those arguments. In the case of printf, that means a string with encoded type information like %d meaning int. If you lie about the type or number, the function has no standard way of knowing, although some compilers have the ability to check and give warnings when you lie.
Please don't use printf("%s", your_string.c_str());
Use cout << your_string; instead. Short, simple and typesafe. In fact, when you're writing C++, you generally want to avoid printf entirely -- it's a leftover from C that's rarely needed or useful in C++.
As to why you should use cout instead of printf, the reasons are numerous. Here's a sampling of a few of the most obvious:
As the question shows, printf isn't type-safe. If the type you pass differs from that given in the conversion specifier, printf will try to use whatever it finds on the stack as if it were the specified type, giving undefined behavior. Some compilers can warn about this under some circumstances, but some compilers can't/won't at all, and none can under all circumstances.
printf isn't extensible. You can only pass primitive types to it. The set of conversion specifiers it understands is hard-coded in its implementation, and there's no way for you to add more/others. Most well-written C++ should use these types primarily to implement types oriented toward the problem being solved.
It makes decent formatting much more difficult. For an obvious example, when you're printing numbers for people to read, you typically want to insert thousands separators every few digits. The exact number of digits and the characters used as separators varies, but cout has that covered as well. For example:
std::locale loc("");
std::cout.imbue(loc);
std::cout << 123456.78;
The nameless locale (the "") picks a locale based on the user's configuration. Therefore, on my machine (configured for US English) this prints out as 123,456.78. For somebody who has their computer configured for (say) Germany, it would print out something like 123.456,78. For somebody with it configured for India, it would print out as 1,23,456.78 (and of course there are many others). With printf I get exactly one result: 123456.78. It is consistent, but it's consistently wrong for everybody everywhere. Essentially the only way to work around it is to do the formatting separately, then pass the result as a string to printf, because printf itself simply will not do the job correctly.
Although they're quite compact, printf format strings can be quite unreadable. Even among C programmers who use printf virtually every day, I'd guess at least 99% would need to look things up to be sure what the # in %#x means, and how that differs from what the # in %#f means (and yes, they mean entirely different things).
use myString.c_str() if you want a c-like string (const char*) to use with printf
thanks
Use std::printf and c_str()
example:
std::printf("Follow this command: %s", myString.c_str());
You can use snprinft to determine the number of characters needed and allocate a buffer of the right size.
int length = std::snprintf(nullptr, 0, "There can only be %i\n", 1 );
char* str = new char[length+1]; // one more character for null terminator
std::snprintf( str, length + 1, "There can only be %i\n", 1 );
std::string cppstr( str );
delete[] str;
This is a minor adaption of an example on cppreference.com
printf accepts a variable number of arguments. Those can only have Plain Old Data (POD) types. Code that passes anything other than POD to printf only compiles because the compiler assumes you got your format right. %s means that the respective argument is supposed to be a pointer to a char. In your case it is an std::string not const char*. printf does not know it because the argument type goes lost and is supposed to be restored from the format parameter. When turning that std::string argument into const char* the resulting pointer will point to some irrelevant region of memory instead of your desired C string. For that reason your code prints out gibberish.
While printf is an excellent choice for printing out formatted text, (especially if you intend to have padding), it can be dangerous if you haven't enabled compiler warnings. Always enable warnings because then mistakes like this are easily avoidable. There is no reason to use the clumsy std::cout mechanism if the printf family can do the same task in a much faster and prettier way. Just make sure you have enabled all warnings (-Wall -Wextra) and you will be good. In case you use your own custom printf implementation you should declare it with the __attribute__ mechanism that enables the compiler to check the format string against the parameters provided.
The main reason is probably that a C++ string is a struct that includes a current-length value, not just the address of a sequence of chars terminated by a 0 byte. Printf and its relatives expect to find such a sequence, not a struct, and therefore get confused by C++ strings.
Speaking for myself, I believe that printf has a place that can't easily be filled by C++ syntactic features, just as table structures in html have a place that can't easily be filled by divs. As Dykstra wrote later about the goto, he didn't intend to start a religion and was really only arguing against using it as a kludge to make up for poorly-designed code.
It would be quite nice if the GNU project would add the printf family to their g++ extensions.
Printf is actually pretty good to use if size matters. Meaning if you are running a program where memory is an issue, then printf is actually a very good and under rater solution. Cout essentially shifts bits over to make room for the string, while printf just takes in some sort of parameters and prints it to the screen. If you were to compile a simple hello world program, printf would be able to compile it in less than 60, 000 bits as opposed to cout, it would take over 1 million bits to compile.
For your situation, id suggest using cout simply because it is much more convenient to use. Although, I would argue that printf is something good to know.
Here’s a generic way of doing it.
#include <string>
#include <stdio.h>
auto print_helper(auto const & t){
return t;
}
auto print_helper(std::string const & s){
return s.c_str();
}
std::string four(){
return "four";
}
template<class ... Args>
void print(char const * fmt, Args&& ...args){
printf(fmt, print_helper(args) ...);
}
int main(){
std::string one {"one"};
char const * three = "three";
print("%c %d %s %s, %s five", 'c', 3+4, one + " two", three, four());
}

How to create a va_list on GCC?

I'm trying to convert some code so that it compiles on gcc too (right now, it compiles only on MSVC).
The code I'm stuck at is in a pseudo-formatting function that accepts as input a format string and zero or more arguments (const char *format, ...). It will then process some of the placeholders consuming some of the arguments, and pass the rest to vsprintf along with a new va_list dynamically generated.
This is the actual code for generating the new va_list:
char *new_args = (char *) malloc(sum);
char *n = new_args;
for(int i = 0; i < nArgs; i++)
{
int j = order[i];
int len = _getlen(types[j]);
memcpy(n, args + cumulOffsets[j], len);
n += len;
}
vsprintf(buffer, sFormat.c_str(), new_args);
In my defense, I didn't and would never write this code. In fact, I think it's one of the most hackiest things I've seen in my whole life.
However, this function is very complex, very old, and very important. It's also hasn't been modified in years (well, except now) so while I'd like to rewrite it from scratch I can't justify the time it would take plus the bugs it would introduce.
So, I need a way to do this same thing on GCC.. But there a va_list is not a char * so I'm getting:
error: ISO C++ forbids casting to an array type '__va_list_tag [1]'
I'm a bit lost. Why do you need a new dynamically-generated va_list? Why not just reuse the old one?
I believe vsnprintf() uses a current va_list object (if you can call it that). So you are free to va_start(), use the arguments you want via va_arg(), then pass the remaining arguments via the va_list to vsnprintf(), and then call va_end().
Am I missing something? Why the deep copy?
And if you do need a deep copy, why not va_start() fresh, remove the arguments you want via va_arg(), and then pass the resulting va_list object to vsnprintf().
(Each call to va_arg modifies the va_list object so that the next call returns the next argument.)
Alternatively, you could just use va_copy(). (Though be sure to follow it with a corresponding va_end().)
Addendum: Also note that these va_ macros are based on C89 & C99 standards. GNU g++ will support them. Microsoft is somewhat more limited.
Following up on TonyK's comment:
What I said above works if you are pulling the first N items off the va_list. If you are pulling items out of the middle, that's harder.
There is no portable way to construct a va_list.
However, you could pull apart the format string, use it to determine the object types (double,float,int,etc), and print each one out individually with it's own format string (a subsection of the original format string). The multiple snprintf() calls will cause some overhead. But if this routine isn't called too often, it should be viable.
You could also print out subsections of the original format string with a suitably crafted va_list. In other words, the first vsnprintf() call prints elements 1..3, the second elements 5..7, the third 10..13, etc. (As vsnprintf() will ignore extra elements on the va_list beyond what it needs. You just need a series of corresponding format-string-fragments, and popping items off the va_list with va_arg() as needed for each vsnprintf() call.)
There's not enough context to figure out what you're trying to do here, but if you need to COPY a va_list, you may be able to use the C99 standard function va_copy, which gcc supports (but I have no idea if MS supports it).
There is a way to do this, it isn't pretty:
union {
char *pa;
va_list al;
} au;
....
au.pa = new_args;
vsprintf(buffer, sFormat.c_str(), au.al);
Using a union instead of a cast is ugly, but you can't cast if va_list is an array type.