这是一道关于符号调试器实现原理的讨论题。目的不是考察调试经验或者调试器设计,而是想借助这个话题来考察候选人的计算机基础知识和工作性格。一般这样开头:
有用过调试器吧?都用过那些功能?接下来和候选人探讨调试器背后的实现原理,比如如何实现查看变量,查看内存,查看调用栈,如何实现断点等。
选择这个话题的原因之一是有话可说,几乎所有程序员都有使用调试器的经历;其二是绝大多数人都没有亲自设计调试器的机会,反馈出来的信息能反映候选人的真实水平。
好处之一,识别没有钻研精神的候选人
我理解很多工程师在生产活动中并不使用调试器,但是调试器基本上是初学编程阶段的必备工具。在初学者眼中,调试器就像一个上帝般的存在,他和我们自己编写的程序有很大的不同–他能窥探和操纵别的程序。很难想象一个对计算机软件真正感兴趣的程序员从来没有考虑过这家伙背后的原理。
如果一个工程师从来不思考调试器的原理,那么他及有可能也不会去思考数据库的原理,不会去思考操作系统的原理,甚至也不会去思考经常使用的某个第三方库的原理。这些没有思考过的地方都是他的知识盲区,导致他永远无法有把握的编程。而且这种候选人有个对工程师来说的致命伤–缺乏主动探索的好奇心。通常进来有什么技能,出去还是那些技能。
好处之二,识别基础知识有瑕疵的候选人
当我们讨论如何获取调用栈,如何查看变量时,真实的意图是考察候选人对程序运行时刻环境的理解;当我们讨论断点的设计时,其实也是在考察类似于中断/信号这种体系结构/操作系统方面的基础知识。
这些知识是编写靠谱软件最最基本的知识,比数据结构还要基础。搞不清楚调用栈布局的工程师无法理解局部变量写越界后程序为什么飞到一个莫名其妙的地方,因此他很难真正理解安全编程规范;而理解了对象运行时形态的工程师不会无意识写出故意和垃圾回收做对的代码;有些工程师在软件不能正常工作时只能通过不断回退版本分析代码文本来定位,没办法拿着core dump直接了当的分析问题,原因就是他脑袋里只有源代码,没有程序的运行时模型。换句话说他其实就是一个逻辑编程者,没错,这就是有人认为数学过关就能编好程序的原因。
实战中的反馈
以下是面试过程中收到的一些反馈:
如果是嵌入式工程师,他们会讲到JTAG的原理
如果是c/c++程序员,他们会聊到编译原理,操作系统,处理器
如果是java或者python程序员,他们会聊到虚拟机,聊到运行时对象模型
下次招人的时候,我推荐你不妨也试试这把锤子。它未必能帮你发现优秀的程序员,但是能帮你识别不靠谱的程序员。