Sebastian Sito
Sebastian Sito

Reputation: 163

Passing variable num of args to another method in class

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

Answers (2)

David Schwartz
David Schwartz

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

David D
David D

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

Related Questions