Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is accidental macro substitution?

What is accidental macro substitution?

In Vera++ C++ linter, rule T016 states:

The calls to min and max functions should be protected against accidental macro substitution.

x = max(y, z); // wrong, vulnerable to accidental macro substitution

x = (max)(y, z); // OK

x = max BOOST_PREVENT_MACRO_SUBSTITUTION (y, z); // OK

Why is this a good rule, and what is so special about min and max functions that require this rule?

like image 458
Victor Lyuboslavsky Avatar asked Mar 16 '13 15:03

Victor Lyuboslavsky


People also ask

What is macro substitution directives?

Macro substitution is a mechanism that provides a string substitution. It can be achieved through "#deifne". It is used to replace the first part with the second part of the macro definition, before the execution of the program. The first object may be a function type or an object.

What is macro programming?

In computer programming, a macro (short for "macro instruction"; from Greek μακρο- 'long, large') is a rule or pattern that specifies how a certain input should be mapped to a replacement output. Applying a macro to an input is known as macro expansion.

When would you program a macro?

Macros can be used for abbreviation, abstraction, simplification, or structuring. Many application programs, such as word processors or spreadsheets, offer a macro language for writing scripts or subroutines that bundle a number of simpler actions into one command.


1 Answers

Accidental macro substitution is unintentional use of a macro whose name conflicts with a function.

The situation Vera++'s checks are designed to prevent occurs when misbehaved system headers — most famously <windows.h> — define min and max macros that interfere with application-defined functions of the same name or even with standard library functions such as std::min<T>, std::max<T>, and std::numeric_limits<T>::min(). (Other names have been known to cause clashes as well.)

Since macros are not namespace-aware, invoking the functions as std::min(...) doesn't help because min is still expanded by the preprocessor. To work around this issue, such functions must be invoked as (function)(args...), which will prevent macroexpansion provided it is defined as #define function(arg1, arg2) ..., as is typically the case with min and max. Another available option is to #undef them before usage, but after including the misbehaving header. Boost provides its own substitution prevention marker, although its self-descriptiveness is offset by the clutter it introduces.

If you control inclusion of <windows.h>, you can also #define NOMINMAX prior to its inclusion, which will instruct windows.h not to define the min and max macros.

like image 132
user4815162342 Avatar answered Oct 05 '22 02:10

user4815162342