SBRM/RAII for std::va_list/va_start()/va_end use
Asked Answered
B

2

8

My code contains snippets like these:

    std::va_list ap;
    va_start(ap, msgfmt);
    snprintf_buf buf;
    const tchar * msg = buf.print_va_list(msgfmt, ap);
    va_end(ap);

These are short and va_start() and va_end() are close together so they are not much of a problem. Exceptions from calls in between the two could be a problem (or not?).

Simple test shows that calling va_start() from a function without ellipsis is not allowed. Is calling va_end() from a different function than va_start() was called from allowed or not?

Basically, I am curious if it is possible to use the SBRM/RAII idiom for these calls, even if it were necessary to call va_start() manually and then to pass instance of std::va_list into my RAII/SBRM guard instance?

Broadcaster answered 27/8, 2012 at 12:14 Comment(0)
S
10

Unfortunately, no. The specification of va_start and va_end requires that:

Each invocation of the va_start and va_copy macros shall be matched by a corresponding invocation of the va_end macro in the same function.

Therefore, va_end must be in the variadic function itself, not a class destructor.

Sanderson answered 27/8, 2012 at 12:46 Comment(1)
@wilx: The C99 standard, 7.15.1/1.Sanderson
P
0

One of possible implementations assumes std::va_list = char* and va_end() is just setting that pointer to null. Of cause, it can be called outside of function. But I'm not sure, that it will works similar on other platforms.

Better to wrap this functions with a class.

Paff answered 27/8, 2012 at 12:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.