The approach you are taking is very sane, safe and sound by itself. For example, the below program is using variadic template arguments and forwards them to std::printf()
, which is a C-style function that accepts variable number of arguments:
#include <utility>
#include <cstdio>
template <unsigned int S, typename ...T>
void my_printf(const char (&fmt)[S], T&&... args) {
std::printf(fmt, std::forward<T>(args)...);
}
int main(int argc, const char* argv[]) {
my_printf("Hello, %s!\n", "World!");
my_printf("I will count to %u...\n", 10);
for (int i = 0; i < 10; ++i)
my_printf("%s %s %u\n", "...", "and", i + 1);
my_printf("And here are my arguments :)\n");
for (int i = 0; i < argc; ++i)
my_printf("argv[%u] == %s\n", i, argv[i]);
}
The problem with undefined behavior and possibly stack corruption is caused by something else. In C++, this is most likely caused by passing non-POD types though C's variable argument list (i.e. passing std::string
to printf()
can do this).
Unfortunately, compiler extensions like "format attribute" won't help here. But compiler might warn you about non-POD types. For example, call my_printf()
with std::string
and you will be rewarded with a warning similar to this:
./test.cc:7:46: error: cannot pass objects of non-trivially-copyable type ‘class std::basic_string<char>’ through ‘...’
std::printf(fmt, std::forward<T>(args)...);
^
Of course, there could be something else going on that compiler won't be able to catch for you. Unfortunately, there is no better way than to debug your program and see what exactly is causing it to crash.
Since you are entering dark waters of C and unsafe arguments passing, debugger is your friend here, and I'd also recommend you use Valgrind - it is very helpful catching things like that.
Hope it helps. Good Luck!