John
John

Reputation: 41

vsnprintf and varargs not working, weird results

I'm using vsnprintf (as far as I know correctly) but am getting weird results. I've simplified my code down to the following example:

void func(char *aaa, ...)
{
    char *buf;
    va_list args;
    int size;

    va_start(args, aaa);
    size = vsnprintf(NULL, 0, aaa, args)+1;
    buf = malloc(size);
    vsnprintf(buf, size, aaa, args);
    printf("%s",buf);
    free(buf);
    va_end(args);
}

int main(int argc, char **argv)
{
    func("abc %s", "def\n");
    return 0;
}

I'd expect "abc def" to get printed, but instead I get "abc" followed by some garbage text. Does anyone have an idea of where I messed up?

Upvotes: 4

Views: 1233

Answers (2)

2501
2501

Reputation: 25753

When you pass the handle args to vsnprintf() it will change it internally in your case. If used again it will not give the correct arguments.

Use va_copy() to create a copy of args if you wish to get your optional arguments twice.

void func(char *aaa, ...)
{
    char *buf;
    va_list args , argsc ;  //argsc is used in the second vsnprintf()
    int size;

    va_start(args, aaa);
    va_copy( argsc , args ) ; //make a copy of args
    size = vsnprintf(NULL, 0, aaa, args)+1;
    buf = malloc(size);
    vsnprintf(buf, size, aaa, argsc);  //use the copy since args is not valid
    printf("%s",buf);
    free(buf);
    va_end(args);
    va_end(argsc);  //destroy both
}

Upvotes: 4

Deduplicator
Deduplicator

Reputation: 45674

va_start(args, aaa);
size = vsnprintf(NULL, 0, aaa, args)+1; // Reads all arguments
buf = malloc(size);
vsnprintf(buf, size, aaa, args); // Tries to read all arguments again
printf("%s",buf);
free(buf);
va_end(args);

See the commented lines. You have to reset args between those two calls consuming all arguments.

Insert:

va_end(args);
va_start(args, aaa);

Upvotes: 4

Related Questions