1

我经常使用 gdbServer 来调试远程 Android 应用程序。我设置断点的区域是一个共享库,用 C++ 编写。

单步执行代码非常慢。有人知道为什么吗?我的假设是对库的 JNI 调用会产生很大的延迟。

4

1 回答 1

1

我的假设是对库的 JNI 调用会产生很大的延迟。

当您在断点处并step在 GDB 中执行命令时,实际上并没有发生 JNI 调用(您已经在本机代码中,只是继续到下一行,或者进入下一个函数,JNI 与它有什么关系?)

不幸的是,step即使在本机执行时也可能很慢;对于优化的代码尤其如此。

step指挥如何运作?理论上,GDB 可以检查当前行的指令,发现没有CALLs 和JMPs,在下一行设置一个第一条指令的临时中断,然后继续。那会很快,但这不是 GDB 的实际工作方式。

相反,它的作用更简单:它单步执行处理器,并在每条指令处询问“我现在是否停止在上次停止的同一行上?”。如果“是”,再次单步,直到答案为“否”。您可以通过设置来观察此行为set debug infrun 1

根据您当前行有多少指令,完成您的step命令可能需要 100 个单步。使用本机调试可能会很慢,使用远程 gdbserver 时它可能会变得更慢,因为每次单步完成时,GDB 都需要询问 gdbserver“我现在在哪里”。这是在 GDB 和 gdbserver 之间传输的大量数据包。您可以使用 观察这些数据包set debug remote 1

因此,这些因素

  • GDB 远程协议很“健谈”,
  • 每个数据包都需要通过(相对)慢速链路到达设备并返回,并且
  • 一个单曲step可能涉及其中的 100 个

step结合起来产生您观察到的非常缓慢的执行。

一种可能的解决方法是避免执行steps. 相反,设置断点,并在每个处检查程序状态。最终,您将到达错误“下游”的断点(即程序已经处于错误状态)。现在在“上游”的某个地方设置一个新断点,然后查看那里的状态。使用“分而治之”的方法,您很快就会解决问题。

于 2011-11-10T07:32:27.910 回答