Reputation: 7750
I've noticed some problem with va_start
when call successively in two functions. A basic example would be the following one :
std::string format(std::string fmt, ...)
{
char buf[2000];
va_list aq;
va_start(aq, fmt);
vsprintf(buf, fmt.c_str(), aq);
va_end(aq);
return std::string(buf);
}
void error(std::string fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf("%s", format(fmt, ap).c_str());
va_end(ap);
exit(1);
}
int main()
{
int x = 10;
printf("%s", format("Test %d\n", x).c_str());
error("Test %d\n", x);
}
produces
Test 10
Test -1078340156
It seems that, when using the error
function the arguments are corrupted.
What would be the right way to pass the va_list
to another function ?
Upvotes: 2
Views: 4549
Reputation: 372814
You would pass the va_list
explicitly as an argument. Passing a va_list
to a function taking multiple parameters does not "unpack" those parameters. Instead, it just calls the function with two parameters, the second of which is a va_list
. The reason you're getting garbage out of the function is that it's trying to interpret that va_list
as one of the arguments to printf
, causing undefined behavior.
This is why there are functions like vsprintf
- it's so that functions like printf
or sprintf
can internally call a helper function to do the formatting, given the va_list
of arguments.
For example:
std::string vformat(std::string fmt, va_list args) {
char buf[2000];
vsprintf(buf, fmt.c_str(), args);
return std::string(buf);
}
void error(std::string fmt, ...) {
va_list ap;
va_start(ap, fmt);
printf("%s", vformat(fmt, ap).c_str());
va_end(ap);
exit(1);
}
Though, that said, in C++ you should be using variadic templates to do this, because those can be forwarded correctly, are fully type-safe, and (if you implement it correctly) don't risk buffer overruns.
Hope this helps!
Upvotes: 11