2

これは、 のスマートなバリアントを検索した結果ですNSLog()。の重要な機能の 1 つは、リリース ビルドとディストリビューション ビルドでBetterLog()は、NSLog()置き換えが何もコンパイルされないことです。提案された解決策 (たとえばIs it true that one should not use NSLog() on production code? を参照) は、プリプロセッサ シンボルを定義しBetterLog()て、ビルドの種類に応じて の定義を制御することです。通常:

#ifdef DEBUG_MODE
    #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
    #define DebugLog( s, ... ) 
#endif

whereDEBUG_MODEは、デバッグ ビルド専用のプリプロセッサ シンボルとして定義されます。

ただし、多くの場合、つまり、ログ ステートメントが中間変数を使用して構築された場合、結果は未使用の変数に対するコンパイラ警告です。次に例を示します。

if (error) {
    NSString *titleString = @"Error downloading thumbnail, will rebuild it";
    NSString *messageString = [error localizedDescription];
    NSString *moreString = [error localizedFailureReason] ? [error localizedFailureReason] : NSLocalizedString(@"Check the URL.", nil);
    BetterLog(@"%@: %@. %@", titleString, messageString, moreString);
} // silently ignoring *this* error is OK.

ここでは、3 つの文字列すべてがコンパイラの警告を生成します。そして、コンパイラの警告が嫌いです。

もちろん、何らかの条件付きで変数宣言自体を含めずに回避することは不可能です。次の試みを行いましたが、うまくいきませんでした。

単純DEBUG_MODEにデバッグ モードでのみ定義するのではなく、デバッグ モードでは値 1、リリース モードでは値 0 で常に定義します。

次に、コンパイラのデッド コード ストリッピングの最適化を利用しようとしました。

if (DEBUG_MODE && error) {
    // snip
}

コードは問題ありません。リリース モードで正しく削除されています。それでも、コンパイラは未使用の変数の警告を出します。

問題は、醜いものよりも良いことはできないかということです:

#if DEBUG_MODE
if (error) {
    // snip
}
#endif
4

1 に答える 1

1

1つのオプションは次のとおりです。

#define BetterLog(...) do { (void)(__VA_ARGS__); } while (0)

これには、BetterLog() に到達すると、その引数の副作用が評価されるという利点があり、それはクリーンなステートメントであるため、記述するバグではありませんif (x) BetterLog(@"%@", x);(マクロを使用して次のステートメントを壊す可能性があります)。

個人的には、デバッグ コードを除外することが明示されているため、「醜い」プリプロセッサ アプローチを使用することを好みます。

于 2010-09-13T15:14:49.167 に答える