我经常使用 gdbServer 来调试远程 Android 应用程序。我设置断点的区域是一个共享库,用 C++ 编写。
单步执行代码非常慢。有人知道为什么吗?我的假设是对库的 JNI 调用会产生很大的延迟。
我经常使用 gdbServer 来调试远程 Android 应用程序。我设置断点的区域是一个共享库,用 C++ 编写。
单步执行代码非常慢。有人知道为什么吗?我的假设是对库的 JNI 调用会产生很大的延迟。
我的假设是对库的 JNI 调用会产生很大的延迟。
当您在断点处并step
在 GDB 中执行命令时,实际上并没有发生 JNI 调用(您已经在本机代码中,只是继续到下一行,或者进入下一个函数,JNI 与它有什么关系?)
不幸的是,step
即使在本机执行时也可能很慢;对于优化的代码尤其如此。
step
指挥如何运作?理论上,GDB 可以检查当前行的指令,发现没有CALL
s 和JMP
s,在下一行设置一个第一条指令的临时中断,然后继续。那会很快,但这不是 GDB 的实际工作方式。
相反,它的作用更简单:它单步执行处理器,并在每条指令处询问“我现在是否停止在上次停止的同一行上?”。如果“是”,再次单步,直到答案为“否”。您可以通过设置来观察此行为set debug infrun 1
。
根据您当前行有多少指令,完成您的step
命令可能需要 100 个单步。使用本机调试可能会很慢,使用远程 gdbserver 时它可能会变得更慢,因为每次单步完成时,GDB 都需要询问 gdbserver“我现在在哪里”。这是在 GDB 和 gdbserver 之间传输的大量数据包。您可以使用 观察这些数据包set debug remote 1
。
因此,这些因素
step
可能涉及其中的 100 个step
结合起来产生您观察到的非常缓慢的执行。
一种可能的解决方法是避免执行step
s. 相反,设置断点,并在每个处检查程序状态。最终,您将到达错误“下游”的断点(即程序已经处于错误状态)。现在在“上游”的某个地方设置一个新断点,然后查看那里的状态。使用“分而治之”的方法,您很快就会解决问题。