Do I need va_end when throwing an exception?

I have a logging system based on printf formatting:

 void Logger::debug(const char *fmt, ...) { va_list args; va_start(args, fmt); this->output(DebugLevel, fmt, args); va_end(args); } 

If Logger::output reports, will the compiler spin the stack correctly, or do I need to add a try / catch block with va_end(args) to the catch clause? Could it be RAII'ed instead, or is va_end too magic for this? If possible, provide references to the standard.

+6
source share
3 answers

No, they cannot. The motives that they cannot, because they are macros, are stupid. Macros can be used from constructors and destructors without any problems. However, va_start and va_end have special requirements that must be called from the same function. Incorrect movement of them into separate functions. C ++ refers to the C standard, and the C standard says: "Each va_start and va_copy macro call must correspond to a corresponding va_end macro call in the same function." (7.15.1) If you call va_end from the helper class destructor, it may or may not work. Since it does not meet the requirements of the standard, the behavior is undefined.

Edit: just like for another question, you generally need va_end when throwing an exception, a legitimate argument can be made that โ€œcalling the va_end macro does not really require the code to reach the target point at which you call this macro (since the macro call "This is strictly a compile-time action), but he strongly suggests you do it. So yes, use try / catch if exceptions are possible. Justification C99 in its description of va_copy briefly notes that va_start can allocate memory. (I don't know the implementation where he really does.) In such a implementations of va_end then free this memory, so skipping va_end will result in a memory leak.

+6
source

No va_start and va_end are macros. Therefore, they cannot be RAII 'ed. In addition, exceptions do not require special care.

+1
source

Yes, it can be RAII'ed using Boost.ScopeExit , although va_start / va_end are macros.

0
source

Source: https://habr.com/ru/post/921272/


All Articles