下面都是在lldb使用脚本调试和javascript上踩过的坑
先是lldb中使用脚本:
首先不要在python脚本中,用debugger对象执行lldb的调试指令continue,这样程序继续运行但同时也使你的调试器无法对被调试的程序进行中断或停止,如果通过xcode的话,只能关闭xcode。
第二,如果你在同一调用层(或者说一个函数的执行体内),使用了debugger来HandleCommand或者是用debugger的interpreter来HandleCommand,后面就不能接着使用print
def func1(debugger, command): debugger.HandleCommand(command) print 'any thing' # compile-time error def func2(debugger, command): # get retobj # get interpreter interpreter.HandleCommand(command) print 'any thing' # compile-time error
def func(debugger, cmmand): debugger.HandleCommand(command) if True: print 'any thing' # fine
这样将不能在同调用层(或者说同一函数的执行体)内使用print输出信息,因为会报脚本编译错误,语法上没有错误,但是却不能编译通过。
接着是javascript没有严格的语法检查,这个地方比较不容易发现的低级错。
如果变量名拼写错误,但并没有人提醒你,有个地方你可能拼写错了变量名,于是程序运行,但到了拼写错了变量名的地方就不能正常运行,然而你却无从知道有变量名拼写错误了。
同样的情况,是属性访问。因为属性是运行期的属性,而非编译时确定的属性。同样没有检查器为你把第一道关。假设a.upcast.attach是正确的属性访问,但拼写错误成了a.upcastattach(漏了一个属性访问点),或者任一层属性名拼写有误成a.upcaat.attach或a.upcast.attah。上面的情况都是合法的,因为属性的访问将翻译成以属性名为key的键-值访问,所以a.upcastattach将可能翻译成getProperty(a, "upcastattach")。这种情况也不容易发现的。
另一个也是比较隐蔽不易发现的错,请看下面代码两段代码,你能发现会发生什么事?
function foo1(obj) { for(i = 0; i < 2; ++i) ; } function func1() { var arr = new Array(); // push many things to arr for(i in arr) foo1(arr[i]); }
function foo2(obj) { for(j = 0; j < 2; ++j) ; } function func2() { var arr = new Array(); // push many (, more than two,) things to arr var j; for(j = 0; j < arr.length; ++j) foo2(arr[j]); }
第一种情况运行没问题,因为for(in)与for(;;)使用的变量不同一物。
但是第二种情况,运行进入了死循环,因为for(j=0;;)中的j优先使用全局变量,不但如此,还优先按调用层向上使用同名的变量,所以在foo2中for(j=0;;)的j竟然使用了它的调用者func2的变量j,因而使到func2中的循环在每次经过foo2后,j都变成同一值,无法跳出循环。
2018年补充:
如果当时懂得用浏览器去调试js脚本的话,就可以节省更多时间,用在工具的思路上。当时的不足,现在来看不单忏愧,更多的是可惜,浪费了时间。