It's very tempting to have functions like this in your C++ class:
class Foo {
public:
void write(const char* format, ...);
void write(const chat* format, va_list args);
}
The variadic function would be implemented like this:
void Foo::write(const char* format, ...) {
va_list args;
va_start(args, format);
write(format, args);
va_end(args);
}
It looks nice and clean -- a perfect application of overloading.
However there's a subtle problem! The C++ compiler will always try to resolve the method with the most specific signature when it encounters an overloaded call.
Calls like this are fine:
foo->write("%s\n", "Hello");
foo->write("...world");
But what if you have an argument which looks like a va_list? For example, if va_list is a pointer on your platform, what does this line do?
foo->write("How many chickens? Answer: %d\n", 0);
In C++ 0 isn't just a number. It's also the NULL pointer. The compiler will decide that you're actually calling the non-variadic function and will use NULL for the va_list argument. Then your program will crash when you try to read an int argument from a NULL va_list.
Lesson learned. Don't overload functions if one of the functions is variadic.
Now I have to go back and fix some code I wrote yesterday...
No comments:
Post a Comment