【问题标题】:How to confirm our code does not call NSAssert in iOS release binary如何确认我们的代码没有在 iOS 发布二进制文件中调用 NSAssert
【发布时间】:2012-08-15 20:04:03
【问题描述】:

我想禁用在构建我们的发布 iOS 二进制文件时发生在我们的代码行中的 NSAssert 调用,然后我想确认它们已被禁用,因为我是超级偏执狂。如何确认它们已被禁用?

为了在我们的发布版本中禁用 NSAssert 调用,我已将 NS_BLOCK_ASSERTIONS=1(来自 here)常量添加到我正在使用 xcodebuild 进行的命令行发布版本中,以便在整个应用程序的构建中阻止 NSAssert,包括它使用的所有静态库的构建。对于数十个静态库,尝试验证在每个库的项目文件中设置此标志的维护量太大,因此首选这种全局方法。它看起来像这样:

xcodebuild -target MyApp -configuration MyReleaseConfig -DNS_BLOCK_ASSERTIONS=1 build

然后确认我们对 NSAssert 的调用确实已被阻止,这就是我正在尝试的方法,也是我寻求建议的地方:我将符号表从生成的二进制文件中转储出来,并寻找 NSAssert 的实际方法宏调用,如下所示:

# Use 'nm' tool to dump symboltable into txt file
/Applications/Xcode.app/Contents/Developer/usr/bin/nm MyApp.app/MyApp > MyApp.symbols.txt

# Search symbols for NSAssertionHandler:
grep "NSAssertionHandler" ./MyApp.symbols.txt

# Output results:
RESULT=$?
if [ $RESULT -eq 0 ]
then
    echo -e "** ASSERTION CHECKER FAILED: FOUND 1 OR MORE NSASSERT CALLS IN RELEASE BINARY **"
else
    echo -e "** ASSERTION CHECKER SUCCEEDED:  NO NSASSERT CALLS IN RELEASE BINARY **"
fi

问题是我仍然看到 NSAssertionHandler 出现在符号中:

U _OBJC_CLASS_$_NSAssertionHandler

我怀疑我使用 nm 不正确;或者,也许这个符号出现是因为我们正在链接使用 NSAsserts 的第三方库,或者 iOS API 本身使用 NSAsserts,从而混淆了我的验证步骤。我希望在我们的发布版本中阻止我们对 NSAssert 的所有代码调用——我如何验证是否是这种情况?任何建议将不胜感激!

【问题讨论】:

  • 在我的发布配置中,我使用“NS_BLOCK_ASSERTIONS=1 NDEBUG”,所以即使你使用 xcodeBuild,你也会选择它们。您还想添加 NDEBUG,因为它会禁用“assert()”(我使用的东西比 NSAssert 多,因为它更容易输入)。
  • 自从两周前发布这个问题以来,我还没有发现任何方法来确认构建确实已经剥离了断言。所以我将继续在我们的正式构建过程中实现命令行设置(-DNS_BLOCK_ASSERTIONS=1-NDEBUG),并且相信它可以工作,因为这是我能做到的最好的做。但如果有人有想法,我仍然很想听听他们的意见。谢谢。
  • 这很容易做到。在 applicationDidLoad 中,然后添加 #ifdef DEBUG\nassert*0);\n#else\nNSLog(@"Asserts are ON");\nendif.你可以用 #if NS_BLOCK_ASSERTIONS == 1\nNSAssert(0, @"Gotcha");\n... 做同样的事情
  • applicationDidLoad 技巧是检测 NSAssertassert 是否存在调用单体应用程序的好主意,谢谢。我的情况需要从链接到我的几十个静态库的应用程序中剥离这些调用,因此我需要确保主应用程序及其库都没有这些调用。这就是为什么我在命令行构建级别对此进行攻击,因为命令行构建参数会覆盖主要应用程序设置,以及十几个静态库的设置(以及偷偷摸摸的 .xcconfig 覆盖等)。
  • 如果我错了,请纠正我,但 NS_BLOCK_ASSERTIONS 不是预处理器宏,因此它只适用于您的源文件,而不适用于任何已经编译的静态库?除非它修改了断言处理程序以便断言保留在代码中但不抛出异常?

标签: ios release nsassert


【解决方案1】:

您可以将NSAssert(false, @"test"); 放在您知道会命中的代码路径中,然后看看它是否会被发布版本命中。

无论如何,因为这是一个老问题,我想知道同样的事情,我想我会提供更新。对我来说,在 Xcode 4.6.3 中,我会自动看到为我的发布版本定义的 DNS_BLOCK_ASSERTIONS=1 - 所以 NSAssert 确实没有编译到发布版本中。

我还在一个总是命中的代码路径中对此进行了测试,并且断言没有被命中。它甚至没有被编译,因为我实际上忘记了@,它甚至不会在 Debug 中编译,而是在 Release 中编译。

【讨论】:

  • 感谢您的更新。我一直在寻找一种可以在命令行上使用的技术,因此我可以将其合并为自动回归测试。你的技术可以工作,但是要跨几十个静态库来验证它们是否也是在禁用 NSAsserts 的情况下构建的会很麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 2013-08-23
相关资源
最近更新 更多