如何避免“未使用的变量”有条件编译的 NSLog 替换的编译器警告?
这是我对 NSLog()
的智能变体的搜索。 BetterLog()
的一个关键特性是,NSLog()
替代品在发布和分发版本中编译为空。建议的解决方案(参见例如 是确实,不应在生产代码上使用 NSLog()?)是定义一个预处理器符号来根据构建类型控制 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
其中 DEBUG_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.
这里所有三个字符串都会产生编译器警告。我讨厌编译器警告。
当然,如果不以某种方式有条件地包含变量声明本身,就不可能避免这种情况。我做了以下尝试,但没有成功:
我不是简单地在调试模式下定义 DEBUG_MODE,而是一直定义它,在调试模式下使用值 1,在发布模式下使用值 0 。
然后我尝试利用编译器死代码剥离优化:
if (DEBUG_MODE && error) {
// snip
}
代码没问题:它在发布模式下被正确剥离。然而编译器仍然发出未使用的变量警告。
所以问题是:有没有可能比丑陋的做得更好:
#if DEBUG_MODE
if (error) {
// snip
}
#endif
This comes out of my search for a smart variant of NSLog()
. One key feature of BetterLog()
is that the NSLog()
replacement compiles out to nothing for release and distribution builds. The proposed solution (see eg Is it true that one should not use NSLog() on production code?) is define a preprocessor symbol to control the definition of BetterLog()
depending on the kind of build. Typically:
#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
where DEBUG_MODE
would be defined as a preprocessor symbol only for debug builds.
However, in a number of cases, namely when the logging statement was built with intermediary variables, the result is a compiler warning for unused variables. Here is an example:
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.
Here all three strings yield compiler warnings. And I hate compiler warnings.
Of course it's impossible to avoid without somehow conditionally including the variables declarations themselves. I made the following attempt, but it didn't work:
instead of simply defining DEBUG_MODE
in debug mode only, I define it all the time, with value 1 in debug mode, and value 0 in release mode.
Then I tried to take advantage of the compiler dead code stripping optimization :
if (DEBUG_MODE && error) {
// snip
}
The code is OK: it is correctly stripped out in release mode. Yet the compiler still emits the unused variable warnings.
So the question is: isn't it possible to do any better than the ugly:
#if DEBUG_MODE
if (error) {
// snip
}
#endif
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一种选择是:
这样做的优点是,如果您到达 BetterLog(),将评估其参数的任何副作用,并且这是一个干净的语句,因此编写
if (x) BetterLog(@ "%@", x);
(这会破坏使用宏的下一条语句)。就我个人而言,我更喜欢使用“丑陋”的预处理器方法,因为它明确排除调试代码。
One option would be:
This has the advantage that if you reach a BetterLog(), any side effects of its arguments will be evaluated, and it’s a clean statement so it’s not a bug to write
if (x) BetterLog(@"%@", x);
(which would break the next statement using your macro).Personally, I prefer to use the “ugly” preprocessor approach, because it’s explicit about excluding the debug code.