2013-03-16 9 views
7

偶発的なマクロ置換とは何ですか?偶発的なマクロ置換とは何ですか?

Vera++ C++のリンターでは、T016は述べルール:

呼び出しがminにして最大の機能は 偶発マクロ置換から保護されなければなりません。

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

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

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

なぜこれが良いルールであり、このルールを必要とminとmax関数についてとても特別な何ですか?

答えて

8

誤ったマクロ置換は、名前が関数と競合するマクロの意図しない使用です。システムヘッダをmisbehaved場合

ヴェラ++のチェックを防止するように設計されている状況が発生した - 最も有名<windows.h> - 同じ名前の、あるいはそのようなstd::min<T>std::max<T>として標準ライブラリ機能を有するアプリケーション定義の機能に干渉するminmaxマクロを定義し、およびstd::numeric_limits<T>::min()。 (その他の名称は、同様に衝突を引き起こすことが知られている。)

マクロは名前空間を認識していないので、minはまだプリプロセッサによって展開されているので、std::min(...)としての機能を呼び出すことは助けにはなりません。この問題を回避するには、このような関数は、およびmaxの場合のように、#define function(arg1, arg2) ...と定義されている場合、マクロ展開を防止する(function)(args...)として呼び出す必要があります。使用可能な別のオプションは、使用前に#undefにありますが、誤動作ヘッダーを含めた後に使用できます。 Boostは独自の置換防止マーカーを提供しますが、その自己記述性は導入する混乱によって相殺されます。

あなたが<windows.h>を含めることをコントロールしている場合、あなたはまた#define NOMINMAXminmaxマクロを定義していないwindows.hに指示しますそのインクルージョンにすることができます。

+0

+1。私が最初に質問したとは全く関係がありませんでした。私が思い出したように、minとmaxの他にもいくつかのものがあります。 – WhozCraig

+0

BOOST_PREVENT_MACRO_SUBSTITUTIONは単に "#define BOOST_PREVENT_MACRO_SUBSTITUTION"です(値は定義されていません)。彼らはマクロのわかりやすい名前を選ぶだけで読めません。 –

+0

'#define NOMINMAX'も同様に役立ちます。 – chris

0

問題は、厄介なライブラリ(または愚かなプログラマー)が、一般的にあなたが期待していない最大と最小のマクロを定義することです。あなたのコードが素晴らしい関数によって評価されると仮定しているなら、不正確な結果(または未定義の動作さえも)を得るでしょう。リンターは、あなたが使用しているすべてのインクルードで定義されているすべてのマクロを知っていることが本当に確実でない限り、そのような一般的なマクロ名で衝突するリスクはない方が安全です。

関連する問題