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