Google
 
Showing posts with label WIND. Show all posts
Showing posts with label WIND. Show all posts

2009-08-19

初步了解google-breakpad

  第一次知道google-breakpad这个东西,是一篇讲chrome使用的开源库的文章,当时也只是一带而过,心想这功能也能做成多平台的?
  最近还是因为项目的需要,原本已经有一个这种实现的,是从FileZilla的2.x版本中抠出来的,不过有些时候会生成不了dump,让人觉得诧异,还有一些是生成了dump,但最后发现栈回调的信息太缺乏可参考的价值了。我估摸着,这可能跟如何使用dbghelp.dll里的函数的方式有关系,而这google-breakpad在我看来可能是当前功能实现得最好的一个了,就打算好好了解一下。
  从svn里取得到的代码,解决方案是用于VC2005的,大概google内部VC都是用的2005吧,看到好些它的开源项目都是。直接用VC2008打开,自动转换版本后,也可以直接编译。主要看src\client\windows\目录下的代码就可以了,一般而言可以用到的有3个lib文件,分别是crash_generation.lib、exception_handler.lib、crash_report_sender.lib。如果用户程序只是为了能生成minidump,直接链接exception_handler.lib就可以了,crash_generation.lib已经被它包含了,而crash_report_sender.lib顾名思义是可以将文件发送到某个地方的,从代码上看,是通过http的上传功能来实现的,不过还没研究。另外还有一个GUI的演示程序,crash_generation_app.exe,可以测试除0异常,CRT函数参数无效异常以及纯虚函数调用异常。
  通过阅读crash_generation_app.exe的代码可以大体上了解google-breakpad的使用方法。google-breakpad将这么一个小功能分成几部分来实现,首先,它分为服务器和客户端两部分,这两部分都可以生成minidump,但应用场景不同。用户程序出现未处理异常时,被ExceptionHandler捕获到,该模块会根据当前进程是否已连接到一个服务器,来决定由谁来生成minidump。在crash_generation_app.exe中默认是会去连接一个服务器的,所以如果服务器没有问题,则是由服务器来生成minidump的。而且服务器生成minidump不限于当前进程,它通过Event得到客户端的dump请求,通过管道进行其他数据的传递。使用C/S结构的好处是,可以尽量减少对被dump进程的影响,代价则是大大增加了代码实现的复杂性。如果没有可连接的服务器,客户端也可自己生成minidump,这部分的实现上网上的所有有关这个主题的代码,基本上都是相同的。唯一有点区别的是,网上其他的代码一般只接管了未处理异常,而google-breakpad则还可以接管CRT函数无效参数异常和纯虚函数调用异常。
  在crash_generation_app.exe的实现中,使用服务器dump的方式,最后返回的结果总是说没成功,而实际是dump文件是生成了的,这应该算是个bug吧。还有个问题是,如果一开始尝试连接到服务器后,后来服务器又被关掉了,那之后的dump会全都失败,这可能是因为演示的缘故,没有仔细编写这种异常流程的处理代码吧。另外,算是小瑕疵吧,用google-breakpad默认好像是不能自定义dump文件的名字,只能指定个保存路径,最后的文件名是随机生成的uuid。
  总的说来,对于有这方面需求的应用,使用google-breakpad是个不错的选择,它做了不少工作。

2009-08-11

可以自动提交dump分析记录了

  今天花了近一天的时间,重新写了一遍自动分析mini dump然后将分析结果提交到wiki上的程序。通过这次实践,也确认了我原先的想法是可行的,内嵌一个IE,然后通过它暴露的COM接口,进行一些基本的操作,主要有遍历已有元素,填充TextArea,提交。只是发现这些操作,全都不是阻塞的,所以具体应用的时候还是得留心一下。
  晚上加班,看了一下一个公司的人写的ppt,介绍Erlang的,看得让我觉得有点不舒服。按我的理解来看这ppt,似乎他的意思是公司目前使用C/C++来开发电信类软件,而且有那么多的问题,而Erlang从语言的机制上就提供了不少的保障机制,可以写出更快更稳的程序来。让我感觉他在鼓吹这就是银弹。就我以为,写这个ppt的目的就不明确,或者说就算明确了,也是动机不纯,我们应该立足于眼前,如何提高公司开发人员的设计和编码水平,而不是考虑着换一种语言就妄图可以解决一堆问题。
  不过总的说来,我看了《Erlang程序设计》中的前面一两章后,就觉得这是我真的需要的一种东西,也许它在保证并发上,或者FP编码风格的处理上并不完美和彻底,但就目前看来,它应该是比较适合我的需求的一个选择。

2009-08-04

x和dt偶尔还是有些用处的

  事实证明,x和dt偶尔还是有些用处的,有几个core dump记录,经过分析后,嗯,是x或dt后,发现就是在倒数第二次或倒数第三次调用某个对象的方法时崩溃的,而崩溃的原因就是因为那个指向对象的指针其实是个0,只要调用的方法引用了什么成员变量,那么对不起,保证完成“死给你看”的任务。想来,在知道用x和dt前,那些问题我估计是分析不出什么结果来的。
  今天,抱着试试看,用VC9重新全部编译了一下Scintilla,发现真可以用了。在这之前的几天里,偶然发现只要向Scintilla发送什么消息,应用程序就会崩溃,还以为是CVS里的代码有问题。
  这软件的问题啊,真是个很缠人的事啊!

2009-08-03

除了!analyze -v外什么都不行

  那些个core dump,都是我抠了FileZilla早期版本中的源代码出来,利用DbgHelp.dll的功能整出来的mini dump,本来有点迷惑的为什么查看变量内容时,老说访问内存错误,又翻了一会儿书才偶然发现,原来是这mini dump本来就只保存了寄存器和栈回调的信息,这也可以理解了,不然加上完整的内存dump,怎么可能只有几十KB大小。于是只好很沮丧地得出一个结论:对于mini dump,除了!analyze -v外,还真的什么都不行。

2009-07-31

除了!analyze -v外

  今天发现,对于core dump文件的分析,除了!analyze -v外,还可以.frame一下,再x或者dt一下的。不过也就只能这么一下了,而且不知道为什么,那时x或dt出来的对于之前调用栈中的内存,显示都是读取错误,而且有时候看地址似乎也真的不对。
  由于发现了x和dt这样的命令,于是今天在分析core dump时也稍微卖力了点,不过最后我却又不得不怀疑我这样的理解是不是正确的,因为有两个core dump到最后分析出来都是因为类指针为空而对它进行提领,而看代码实现是很不像会出现这种指针为空的情况啊!我大汗!
  还是得继续学习啊!

2009-07-30

写程序是件很诡异的事

  上午花了两个多小时,嗯,确实是两个多小时,写了个小程序,每隔一段时间扫描一下指定的文件夹下所有core dump文件,和历史数据库中的记录进行比较,如果历史数据库中没有记录,则认为是新追加的文件,一边将其添加到历史数据库中,一边则使用cdb.exe通过命令行进行分析,最后将分析结果连同那个core dump文件一起通过SMTP协议发送到notes邮箱中。
  其中遇到不少奇怪的问题。本来是打算cdb.exe将分析结果重定向到文件后,自己读一下这个文件的内容,把这个内容作为邮件的正文发送的。结果首先是发现,使用system这个CRT函数,其中是调用了cmd.exe /c这个命令行,所以如果传给这个函数的参数如果同间有空格,是要用双引号包括起来的。尤其要注意的是,如果打算执行的是一个带参数的命令行,得从头到尾一起括起来。接着我就想用ifstream的方式把文件内容读出来,然而很诡异的是,直接将其输入到一个stringstream时,只有一小部分内容读出来了;通过getline一行一行读出来后,本来打算全部追加到另一个string中去的,但是就是追加不进去,最后想使用API吧,直接CreateFile,再ReadFile,内容但是全读出来了,最后通过SMTP发送这部分正文时,依旧只能发送前面一小部分。放弃了,本来就昆个Quick & Dirty的东西,于是还是直接把这个文本文件作为附件发送吧。也不知道是不是那个SMTP类本来就有问题,运行的过程中时不时弹出个出错信息来,什么delete指针时错了呀,堆被破坏了呀,等等等等,不一而足,实在无语得很!
  不过尽管还是会弹错误框,但手工点一下也不麻烦,先这么着吧,至少可以当成一个监视器用了。
  这两天我一直在想一个问题:是不是mini dump只有一个用途——!analyze -v?没有找到答案,但翻遍所有的能找到的参考资料,似乎这个猜想是真的!

2009-02-05

有点想通了

  昨天又看了一下《Contributing To Eclipse》,思路有点清晰了,应该有一个任何地方都能访问到的地方,Eclipse中叫插件注册表,存放着所有插件的描述信息,这样无论是核心还是插件,都可以随时读取到与自己相关的插件的所有必要信息,实现相应的功能。
  之前还疑惑,与界面相关的插件处理流程会自相矛盾,现在看来应该能解决了。首先需要确认一点,暴露被扩展点的,无论是核心还是插件,都可以从插件注册表中读取扩展的信息,比如菜单项名称,这样就可以添加一个新的菜单项,以及维护一个处理关系,Eclipse中有个某某proxy的机制,这形式不重要,关键是暴露被扩展点的那个部分应该在添加了新的菜单项后,能在菜单项被点击时,准确地知道哪个菜单项被点击了,并依赖插件注册表找到对应的处理流程,以我目前的情况而言,即对应的Lua脚本文件,Lua脚本模块名称,以及处理函数名称,然后将这些信息提交给插件运行模块来运行,插件运行模块则又要与插件装载模块合作,如果运行时发现没有对应的模块或函数,则要先装载对应的脚本文件到解释器中。

2008-09-22

从VS2008降到VS2005

  本来想用VS2008来写WIND的,但是这两天遇到几个问题,不得不降到VS2005来用。
  首先是装了Refactor!Pro,在VS2008编辑器变得迟缓无比,敲几下键盘,就会死半分钟,这是无论如何不能忍受的,于是在Refactor!Pro的配置项里改了一番,卡死的情况有所好转,但仍然处于不可用状态!而且在退出VS的时候,会写一个巨大的cache文件,工程中没有多少个文件,都会写入100多MB,估计随着代码量的增加,这个文件的体积也会不断飚升。
  其次是,我从PN中抠出来的Scintilla相关的代码,一添加到工程中后,VS2008就会updating intellisense,而且只updating到半途,VS就崩溃了,屡试不爽,无论是从命令行打开该工程,或者是从界面上打开该工程,都会updating直到崩溃!
  于是,我万般无奈下,尝试用VS2005。降级倒是很容易,直接用文本编辑器打开.sln和.vcproj文件,把里面最开头几行中的版本号改小就行了。再用VS2005打开工程,写几行代码,编译一把,似乎倒是没有在VS2008中的那些问题,只好先用VS2005来写了,生在中国可真幸福。
  这倒都只是IDE的问题,我猜如果只是直接从命令行来编译整个解决方案的话,应该不会有问题吧,而且升级也方便,只是改几个版本号。只是是否有这个必要,一定要用VS2008来编译。以后再说吧,本来最主要的也只是为了体验一下Refactor!Pro重构的快感。

2008-09-13

开始使用WTL进行界面开发

  有点受不了MFC那比较累赘的几个在超大dll,同是Windows平台下做GUI开发,我只好选择了WTL。其实我已经比较习惯MFC那套东西,并没有发现多少网上说的种种使用MFC的不爽,相反我觉得还是挺安逸的,甚至对于使用了四五年VCL的我来说,MFC也没多少不方便的,虽然相对于VCL来说,MFC根本算不上可视化,但我也不清楚为什么自己仍然能这么乐于退回使用这种原始的framework呢!现在唯一让我觉得不爽的竟然是它要拖几个dll文件,也好,刚好学习一下WTL。对于目前我的状态来说,最大的困难是可参考的资料过少,市面上还没发现哪本图书是讲怎么使用WTL的,唯一的一份教程则是CodeProject上那流传甚广多少年前的那几篇文章。
  之前也用过WTL写过一个对话框程序。还有一个输入法辅助程序,本来期望是用它来做皮肤生成器的,结果和众多其他我写的程序一样,只是开了个头,然后就丢下了。如今要写一个比较大的程序,我自己也估计不好规模会有多少,猜一下大概C++代码行会过万吧,另外我希望大部分逻辑都是使用外部脚本扩展来完成。
  虽然几乎一点经验都没有,但还好有现成的代码可以参考,特别巧的是,我那程序中也需要一个代码编辑功能,本来就想好是用Scintilla的,但是我不懂如果在WTL中使用这种自定义的窗口,刚好就可以抄袭那些代码了,哈哈!
  编辑器能正常显示出来了,接下来要把TabbingFramework和DockingFramework加进去,之后再考虑其他问题!

2008-07-09

crash report

  以前对这方面没有多少关注,只是偶然看到LuaEdit用了个叫madExcept的库,可以让Delphi程序在运行时如果崩溃了弹出个看起来比较牛的对话框,显示一些当前进程和当前系统的相关信息,并可以让用户选择是否将这份报告通过email发送回开发者。当时很好奇这是怎么做到的,很希望在自己的程序中也集成进这个功能,但很遗憾地发现,这个库只适用于Delphi,而我偏偏就不是用Delphi的。
  后来,偶然,没错,以是偶然,看到公司网上有人说FileZilla有一部分这种代码,于是找来看了看,才大致了解了基本原理,并直接把这段代码抠出来用在了项目中,但到目前为了,这个功能虽然加进去了,却还没有发挥实际的功用。因为这段代码针对使用VC编译的程序会生成一个dump文件,该文件需要配合编译时的源代码以及编译器生成的pdb文件协同工作才会有实际用途,而我们的项目没有一个良好的机制把各个发布版本配套的源代码和pdb文件归档。
  这些天看了《软件调试》,稍微了解了Windows的错误报告机制,觉得这是一种能很好改善用户体验,帮助开发团队改进软件的方法。
  前段时间读Code::Blocks和CodeLite的源代码时,发现在Windows平台下编译时它们都动态装入了一个叫exchndl.dll的动态链接库,却只是装入,没做其他任何事情。根据代码注释中的只言片语,加上后来去down了Dr.mingw的源代码,发现这个dll就是做了捕获未处理异常,生成报告的工作。
  于是,我就有了现在这个想法,也许这个想法就是微软的错误报告机制的简装版。首先,确定这套机制由三大部件协同完成:1、未处理异常捕获;2、反馈崩溃信息;3、分析处理崩溃信息。在具体实现时,可按这三部分分别处理,未处理异常捕获,就像exchndl.dll一样,只需要提供一个dll,应用程序只需要装入后,什么也不用管了;反馈崩溃信息,可以另外再写个客户端,将报告信息(文件)传送给服务器端;分析处理崩溃信息,也就放在服务器端了,可以自动作些简单的分析(像WinDBG那样的,配合对应的源代码和pdb,可以找到引起崩溃的代码行),根据这代码行,可以给用户显示个html页面,说明一下崩溃原因等等,当然这需要一定的人工介入,而且也是三部分中最复杂的。这些工作都可以通过微软提供的技术来实现,但还是有不小的工作量,比如像WinDBG那样结合pdb和源代码分析dump文件,这都是调试器的一部分功能了,另外再显示html页面,肯定是需要有先例通过人工编制一个页面。
  而且这套机制似乎有个最大的不足,是只适用于VC编译的程序。也许其他的编译套件(Borland、DigitalMars、OpenWatcom、Intel……)也提供了类似的机制,但可能没有VC的完善,不需要人工分析即可定位到源代码行,这是何等方便啊!

2008-07-05

《软件调试》

  从china-pub上买了本《软件调试》,厚达1000多页的大砖头。开始拿到的前面有8页是空白,到china-pub上去说了一下,该书的责任编辑通过email跟我协商,最后又快递了一本正常的过来,我再把有问题的那本快递给她,如此服务质量,也让人称心满意了。
  难得原作者用中文写成,这样就可以让我们中文读者第一时间可以读到如此重量级如此深度的精品专著。
  该书从CPU(Intel x86系)对软件调试的支持、操作系统(Windows)对软件调试的支持、编译器(MS VC)对软件调试的支持三大方面进行了讲述,中间结合VC、WinDbg等实例进行讲解。
  昨天晚上躺在床上,快速地浏览了一遍,让我深深感叹Windows,噢不,应该是微软的强大。微软从操作系统到开发工具,都为软件调试支持了极其强劲而且方便的支持,窥斑见豹,微软做软件是多么认真,多么负责,微软帝国的崛起除了机遇外,其自身实力和不懈努力是起主要作用的。
  翻完这本书,我禁不住想自己写一个应用层的调试器,像OllyDbg那样的。粗略想一下,一个调试器需要具有的最基本的功能:反汇编、CPU寄存器读写、内存读写、单步、断点,以及跟系统相关性比较大的装载模块、内存映射、符号信息读取。这些在Windows上绝大部分都有现成的API可以完成了,除了反汇编比较麻烦点(看看IDA Pro做成什么样了,当然动态调试器是不需要这么复杂的),其他的至少从原理上看,是很简单的,困难的是细节。
  嗯,WIND Is Not Debuggger……