Reputation: 163
I've got following (simplified for example purpose) code and it works:
void log(const string type, const string msg, va_list argp)
{
fprintf(stdout, "[%s] ", type.c_str());
vfprintf(stdout, msg.c_str(), argp);
}
void log_err(const string msg, ...)
{
va_list argp;
va_start(argp, msg);
log("ERROR", msg, argp);
va_end(argp);
}
I would use it in this way:
log_err("test: %d", 5);
However if I would like to move this to class:
class Logger {
public:
Logger() {
//
};
void generic(const string type, const string msg, va_list argp) {
fprintf(stdout, "[%s] ", type.c_str());
vfprintf(stdout, msg.c_str(), argp);
};
void error(const string msg, ...) {
va_list argp;
va_start(argp, msg);
this->generic("ERROR", msg, argp);
va_end(argp);
};
};
Then I got Segmentation fault. I know that tricky thing like va macros could not work within class scopes but I want to know why.
Thanks in advice!
EDIT
Example usage:
Logger logger;
logger.error("test", 5);
Full source:
#include <string>
#include <cstdlib>
#include <cstdarg>
using namespace std;
void log(const string type, const string msg, va_list argp)
{
fprintf(stdout, "[%s] ", type.c_str());
vfprintf(stdout, msg.c_str(), argp);
}
void log_err(const string msg, ...)
{
va_list argp;
va_start(argp, msg);
log("ERROR", msg, argp);
va_end(argp);
}
class Logger {
public:
Logger() {
//
};
void generic(const string type, const string msg, va_list argp) {
fprintf(stdout, "[%s] ", type.c_str());
vfprintf(stdout, msg.c_str(), argp);
};
void error(const string msg, ...) {
va_list argp;
va_start(argp, msg);
this->generic("ERROR", msg, argp);
va_end(argp);
};
};
int main()
{
//log_err("test: %s\n", "str");
Logger logger;
logger.error("test %s", 5);
return 0;
}
I don't want to make these methods static because in original use i have private file descriptors to which I'm writing log messages;
Upvotes: 0
Views: 454
Reputation: 182829
The bug is in this line:
logger.error("test %s", 5);
The %s
format specifier is for a C-style string. 5
is not a C-style string. Use:
logger.error("test %s", "5");
or:
logger.error("test %d", 5);
Upvotes: 3
Reputation: 1591
You're 99% of the way there. change
void generic(const string type, const string msg, va_list argp)
to
void generic(const string type, const string msg, va_list & argp)
Seems you can't copy the list (which is done without the reference)
EDIT:: what I posted above is wrong. The first pass through I just assumed what was provided seg faulted and didn't test without the reference. I removed the reference and everything printed just fine.
Left for people of the future.
Upvotes: 0