2011年11月29日星期二

汇编还是不能丢啊

  最后还是通过看汇编代码定位了问题。那位同事在用数组的时候不检查下标,结果在并发状态下刷到了-1。不过问题的根源还是线程安全性。底层数据引擎设计时并没考虑并发问题,因此才会在正常工作的时候变出非法的数据出来。

  借此机会又再次温习了汇编语言,大学时候学的8086/8088汇编指令虽然早已过时,但思想还算没忘。那些关于现在的大学念了白念的说法,我觉得还是需要探讨。

  之前用tds2dbg完成的工作也有价值,帮我把代码段确定了。C++代码能定位到就这一两句,那么再来对照汇编指令就比较好理解了。

  另外,今天还学习到了LEA指令的相关知识,顺便网摘一篇对我有点帮助的博文:
http://www.cnitblog.com/textbox/articles/51912.html

掌握了更好的BCB程序调试手段


  Borland C++ Builder 5 编译的程序没有PDB,因此要通过Dump文件来分析故障原因就太坑爹了。没有符号文件的话,汇编看起来相当痛苦。
  上次查过,有个办法是使用map2dbg,把map文件转换成dbg文件,这样windbg也能够加载符号文件用于调试。不过map里面只有函数名称,没有代码的行号,所以调试起来还是不是很方便。如果断点是在一个长长的函数里面,而且没有嵌套调用什么函数,那么对于汇编功底不深的我也是一样的郁闷。

  今天下了点决心要解决这个问题,否则调试效率太低了。
  感谢万能的Google,这次我知道了有个开源项目叫tds2dbg。用法和map2dbg类似,生成的dbg文件的确可用,而且在正确的行号上指出了我遇到的问题。这样,Crash就不再是一个问题了。

  值得注意的是:BCB编译选项中,必须打开Compiler->Debugging->Line Number Information,以及Linker里面的Create debug information。否则生成的dbg文件没法用。

2011年11月14日星期一

遇到Bug就像踩了地雷

  大约是八月份的时候,应公司的要求,设计了一个给各产品线通用的日志模块。简单而言,也就是做一个导出C函数的DLL,实现通用的日志读写和管理功能。设计是我做的,实现就交给了另一个同事。然而这个同事没过多久就离职了,因此交接时把草草地写完的代码又回到了我这里来。
  平心而论,代码写得不是很咋地。估计这位同事心已经不在了,只想早早结束了事吧。代码中充满了他此前做过的一个BCB项目的风格,主要的功能是用C风格的代码来实现(例如文件读写等),而工程又是一个VC6的Win32 DLL,里面写了自己的类等等。我看了之后第一感觉就是想推了重写,好不容易才压制住这种想法。
  当时我给自己安排了两天来接收并改造这些代码,后来拖长到了三四天。其实现在想想还不如重构。给我的代码功能测试都通不过,里面Bug一大堆。我这人又是有一点代码洁癖的家伙,遇到空格缩进什么的都忍不住花时间去调。最后终于弄好了,真有点不想再去碰了,虽然我知道值得改进的地方还很多。

  结果今天就碰到了一个藏在其中的Bug。

  这个日志模块被设计为保存加密日志,目的嘛……是为了防止用户抵赖。加密就不能全文加密,否则每来一条日志都得解密再加密,量稍微一大就死翘翘了。差分加密是必须的。设计的时候是对每一条日志的内容进行加密,只留下必要的信息放在每一条的头部以便索引。从性能和安全性方面权衡,当时选择了AES算法。
  代码交到我手上时,之前那个同事大概已经从网上找了一段AES算法封装好了。既然能实现加密解密的功能,我也就没往里面细看。谁知道这玩意儿是线程不安全的。今天专拣双核机器报错,从fseek到fopen查了一圈,终于怀疑到这个AES算法上。浪费了约两个小时时间。

  我估计我有时间可能真得把它给重写了,里面指不定还有什么问题。