【问题标题】:Track all ObjC method calls?跟踪所有 ObjC 方法调用?
【发布时间】:2011-08-28 20:04:37
【问题描述】:

有时在查看别人的大型 Objective-C 程序时,很难知道从哪里开始。

在这种情况下,我认为记录对每个非 Apple 方法的每次调用会很有帮助。

有没有办法做到这一点?基本上,在某个中心位置进行一次更改,并记录每个调用的方法。最好仅限于非 Apple 方法。

【问题讨论】:

标签: objective-c debugging


【解决方案1】:

您可以将环境变量 NSObjCMessageLoggingEnabled 设置为 YES。这将在文件夹 /tmp/msgSends-xxx 中写入所有消息发送的日志。

【讨论】:

【解决方案2】:

您可以向objc_msgSend() 添加一个符号断点,并让它记录第二个参数而不停止。

如何只为您自己的方法执行此操作是一项艰巨的任务。也许您可以检查被调用的类名并做一些魔术来为仅类前缀与您自己匹配的调用设置条件断点?

【讨论】:

  • 好的,我在 objc_msgSend() 内部闯入,如何获得第二个参数?请注意,我不想发送任何客观的 C 消息:(
  • @William - 如何获取第二个参数取决于您的目标,因为模拟器的 x86 ABI 与设备的 ARM ABI 不同。您必须从正确的处理器寄存器或堆栈位置获取值。归根结底,我认为您必须问自己是否真的值得麻烦。如果是,请搜索 darwin ABI 文档。
【解决方案3】:

我不认为记录每一个调用都足够实用,但这里有一个关于这个方向的建议。

附带说明,如果它是一个大型程序,最好有某种文档或介绍性注释,以便人们开始使用代码。

无论如何,每个 Cocoa 应用程序都有一个 applicationDidFinishLaunching... 方法。这是一个很好的起点。一些应用程序还在 Info.plist 文件中定义了它们的主体(或“主窗口”)类。这两件事都可能会提示您哪些类(特别是视图控制器)是最突出的类,以及在程序运行时哪些方法可能具有较长的堆栈跟踪。就像游戏引擎中的游戏循环,或其他一些经常调用的方法。通过在此类方法中放置断点并查看调试器中的堆栈跟踪,您可以大致了解正在发生的事情。

如果它是一个 UI 密集型应用,查看其 NIB 文件和其中使用的类也可能有助于确定您可能正在寻找的应用功能的某些部分。

另一个选项是启动 Time Profiler 工具并选中 Hide missing symbolsHide system libraries 复选框。这不仅可以让您鸟瞰程序内部调用的方法,还可以精确定位最常调用的方法。

通过打开 Time Profiler 记录与您的程序进行交互,您还可以识别程序功能的不同部分并将它们与您的操作关联起来。

【讨论】:

  • 这是一个真正难以找到的错误的救星。谢谢。
  • @alex gray,np。这是什么错误?
【解决方案4】:

Instruments 允许您构建自己的“工具”,它们实际上只是DTrace 变相的脚本。使用菜单选项 Instrument >> Build New Instrument 并选择选项,例如您要跟踪哪个库,当您点击特定功能时要记录什么,等等。去狂野吧!

【讨论】:

    【解决方案5】:

    这是一个有趣的问题。如果解决方案支持多个执行线程并且有某种调用时间线可以报告一段时间内的活动(可能尤其是在以某种方式绘制用户事件的情况下),那么答案会更有趣。

    我通常启动调试器,在主入口点设置断点(例如 - applicationDidFinishLaunching:withOptions:),然后在调试器中运行。

    在 OSX 上,也有一些命令行工具(例如示例和堆)可以提供一些见解。

    似乎某种与乐器的集成可能真的很酷,但我不知道有什么东西可以完全满足您的需求(在考虑之后我现在也想要它)。

    如果要记录线程号、调用地址和一些帧详细信息,那么这些片段似乎可以用来绘制调用时间线。找出合适的库(Apple 提供的或第三方)的逻辑应该存在于 Apple 的 symbolicatecrash 脚本中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 2011-10-16
      • 2012-12-07
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多