2

「リリース」でアサートするために以下のコードを使用しますが、しばらくの間問題はありませんでした。その後、Visual Studio 2010 Pro SP1 が登場し、事態は悪化しました。クルンタル

問題は、次のような健全性チェックを行うコードがある場合です。

#define ASSERT(condition, msg) do { (void)sizeof(condition); } while (0,0)
  // Note: (0,0) is to avoid warning C4127: conditional expression is constant

{
  int result = CallMeOnce();  // its side effects are the important stuff
  // perform additional sanity checks in debug
  ASSERT(result >= 0, "too low");
  ASSERT(result <= 100, "too high");
  ASSERT(!isPrime(result), "too prime");
}

VS2010が吐き出すwarning C4189: 'result' : local variable is initialized but not referenced

私はそれを修正する方法に途方に暮れています:

  • 次のようなコード(void)(condition)は、条件として渡された任意の式を実行します。これは no no
  • ASSERTCallMeOnce()式の中に入れることは不可能です
  • すべての異なる をリファクタリングすることCallMeOnce()はオプションではありません
  • (void)resultif (result == result) {}または(または同等の)ようなスキャフォールディング コードをマクロの外側に記述する必要はありませんUNREFERENCED_PARAMETER(result)。警告を回避するためだけに、コードがさらに読みにくくなり (汚染)、デバッグでコードを記述しているときに忘れやすくなります。また、多くの場所で!

変数専用の別のマクロ (ASSERTU?) を作成することを検討していますが、非常に...風変わりです!
誰かがより良い方法を見つけましたか?

どうもありがとう!

編集:呼び出し元レベルでの変数処理の設定を明確化

4

5 に答える 5

0

どうやら私はどこかに着いたようです!

#define ASSERT(condition, msg) \
  do { \
    if (0,0) { \
      (void)(condition); \
    } \
  } while (0,0)

必須の説明:

(void)(condition);C4189 を抑制しますが、渡された任意の式または関数呼び出しを実行します。

ただし、if (false) {...}(有効な式)「...」が何であれ、実行されないことを確認します。コード最適化フェーズは、それをデッド コードと見なして破棄します (私のテストでは、ブロックのコードはまったく生成されません!)。

最後に、フクロウのトリック(0,0)は C4127 を防ぎます。これは、そもそもまったく役に立たない警告のように見えますが、コンパイル出力の混乱が少なくなります!

このソリューションの唯一の弱点は、conditionコンパイル可能なコードである必要があることです。そのため#ifdef、式の一部を削除すると、エラーが発生します。呼び出された関数のコードもコンパイルしている (呼び出していない) 可能性があります。より多くの研究が役立つでしょう。

于 2013-04-05T17:23:13.557 に答える
0

__pragma(warning(push)) __pragma(warning(disable: 4127))とのペアを使用__pragma(warning(pop))して、回線だけで C4127 を無音にすることができますASSERT

その後、(void)(true ? (void)0 : ((void)(expression)))C4189 を沈黙させます。

これは、アサーション マクロの私自身の実装からの抜粋です。

PPK_ASSERT(expression)マクロは、アサーションが有効か無効かに応じて、最終的に展開されますPPK_ASSERT_3(level, expression)PPK_ASSERT_UNUSED(expression)

#define PPK_ASSERT_3(level, expression, ...)\
  __pragma(warning(push))\
  __pragma(warning(disable: 4127))\
  do\
  {\
    static bool _ignore = false;\
    if (PPK_ASSERT_LIKELY(expression) || _ignore || pempek::assert::implementation::ignoreAllAsserts());\
    else\
    {\
      if (pempek::assert::implementation::handleAssert(PPK_ASSERT_FILE, PPK_ASSERT_LINE, PPK_ASSERT_FUNCTION, #expression, level, _ignore, __VA_ARGS__) == pempek::assert::implementation::AssertAction::Break)\
        PPK_ASSERT_DEBUG_BREAK();\
    }\
  }\
  while (false)\
  __pragma(warning(pop))

#define PPK_ASSERT_UNUSED(expression) (void)(true ? (void)0 : ((void)(expression)))
于 2015-12-05T10:20:39.237 に答える
0

UNREFERENCED_PARAMETERマクロを使用できます。

于 2013-04-04T19:03:37.623 に答える