All Stories

sqlite3的Blob操作,变异……

  本来想当成二进制数据一样把文本内容以Blob形式存入Sqlite3的,结果整了半天,虽然最后存是存进去了,好像不是像我预想中的那样写二进制的Blob,而是就是作为文本存入了。不过倒是知道了对于大块数据的操作,在简单的SQL语句中不能方便地实现时,可以用sqlite3_bind系列API,在SQL语句中可以用问号作为占位符,然后将数据bind到各个占位符上去。这样一来的SQL语句要用statement来执行。  存进去后,取出来也是一个问题,本来以为Blob么,二进制么,还专门从别处移植了一段代码过来,结果那段代码可能有点点问题。反正最后我也是看出来了,因为我是原样照搬地把数据存入的,那么还是原样取出来就行了,我大汗!真不知道如果哪天我真要存入一段二进制数据时,应该怎么办了!大概,存入的方式也要跟着改吧。

在CI中使用bjam构建项目

  不知道什么原因,我的机器上什么VC2008命令行来编译项目,无论是devenv.com还是devenv.exe,都会占满CPU,而真正的编译进程cl.exe却一直慢吞吞地,几个文件的小项目,也不知要等上多少时间,在持续集成时实在忍无可忍。  不过因为之前有一段时间专门学习了一下如何使用bjam,所以我就决定在CI上,使用bjam来构建项目。统计了一下我的项目的情况,有用MFC的,有用WTL的,也有用wxWidgets的,有用VC编译的,也有用MinGW编译的,无论哪种情况,bjam都可以满足需求。  使用bjam的一个比较方便的特性是,它能比较智能地自动为不同的编译器套件使用各自的命令行编译选项,这样使得一个bjam脚本可以同时不同的编译器套件来编译。不过实际使用过程中,还是有些需要区别对待的地方,这可能是因为bjam主要用于boost的构建这个目的而产生吧。  比如对于VC和MinGW,可能链接的库文件是不同的,要么是文件名不同,要么是所在路径不同;链接选项可能不同,也许是boost的原因,bjam在构造exe时,默认是使用控制台子系统,所以需要自己在链接选项中自行指定使用Windows子系统,而该选项在VC和GCC中有细小的描述上的区别。  bjam的另一个比较方便的特性是,它能自动寻找编译器套件默认的头文件路径和库文件路径。这比使用makefile要方便太多了,比如在MinGW中编译一个C++,注意,是C++,不是C,的程序,需要仔细地设置引用路径,而bjam中完全不需要,只需要一行代码就能搞定:exe Hello : Hello.cpp ;这个特性对我的情况来说也是很有帮助的,比如使用MFC的项目,鬼知道它要引入多少头文件路径,还有就是有个工程设计成既可以用VC编译又可以用MinGW编译,所以这又省了不少事。  再扯一个跟bjam关系不是很大的东西,编译使用了wxWidgets的项目。有一个小工具程序,可以方便地得到指定路径中的wxWidgets在编译时使用的选项,那就是wx-config。通过这个小东西,在编写编译脚本时,又可以省掉不少事。在http://wxconfig.googlepages.com/上可以找到Windows的移植版本,不过在bjam中使用时,会有一点点小问题,就是它的输出内容都在最后添加了一个回车,而bjam并不能让用户方便地设定编译选项在命令行上的先后顺序,所以如果恰好它的输出结果被排在命令行的中间位置,那之后的那些选项就被断开了,shell则认为这是两条命令,所以会出错。好在这个Windows移植版本提供了源代码,下载下来,自己稍微修改一下,也就是在输出的那条语句中把最后的std::endl去掉就可以了。  VC在支持预编译头文件时,一般是指定stdafx.h文件,然后加个编译编译选项来实现。在bjam中不能这样直接加编译选项来达到这个目的,而是专门提供了一个叫cpp-pch的规则来实现。不过,对于只在CI上才执行的bjam命令,有没有这个功能都无关痛痒。  VC有个很好用的特性,auto-link,boost就使用这个特性,这也使得在VC上使用boost比在其他编译器套件中要方便,它默认链接的都是静态库,使得发布都省了一些事。在bjam中使用时,只要设定好boost库文件的路径,其他的就不用管了。  在使用了MFC的项目中,会有一些特定的选项,比如它需要再指定程序的入口,这些工作本来都是IDE默默地在后台完成了,使用bjam时就需要自己留心了,一般的做法就是直接看项目属性中的命令行一栏,把一些个性化的设置都提取出来写到bjam编译脚本中去。

两个boost相关网站

  如果胆子足够在,这两个网站上的都是值得试一下的,其中不乏一些好东西,比如日志库就有两个,一个叫Boost.Logging,一个叫Boost.Log。  https://svn.boost.org/trac/boost/wiki/LibrariesUnderConstruction  http://www.boostpro.com/vault/  对于进入boost的侯选库,有两个存放点,一个就是上面第2个地址vault,还有一个是boost svn中的sandbox目录。从Review Schedule中看来,似乎进入Review的库从vault中来得多一点,而sandbox又有点像boost正式库的一个draft。

崩溃问题分析

  这两天在抽空分析程序的崩溃记录,这些记录都按照版本号分别放在不同的文件夹中。早先exe文件的版本号并没有严格对应于svn revision号,周一时用一个修改PE资源的小程序搞定了这个事情,以后做这方面的事可要精确和省神多了。  今天分析到一个记录,印象中以前也有过类似的记录,一时没想起来,发现是一个线程函数数,对一个std::map调用find方法,结果在STL内部引起崩溃了。开始的时候,还以为是调用find方法时传入的参数有问题,引发了STL的某个未定义行为。于是另外写了个小程序简单验证了一下自己的猜想,结果不如自己所料。后来猜测要引用这个map的对象时,包含它的指针已经无效了。但为什么无效,我却也得不出什么结论。最后突然想到,从崩溃记录分析得到的最后堆栈信息中,看到是调用find方法后,find方法中取xtree的根节点引起的崩溃,那么是不是这个map对象本身就是有问题的了呢?灵光一闪,这个map对象是做为一个类的成员的,如果这个类的实例被销毁了,这个map对象自然也跟着被销毁,而这时如果再试图访问它,当然会有问题。  分析出来具体的原因,修改起来就比较容易了,在该类的实例被销毁时,应该通知那个线程马上结束,而且不要再试图去访问那些它的成员了。在修改这块代码的过程中,我应用了boost::thread,这大大简化和缩减了需要编写的代码。

最近Boost有点疯啊

  什么Boost.DirectX啊,Boost.Debug啊,Boost.Cppgui啊,越来越疯狂了哦!

我晕std::locale

  今天一个同事突然发邮件来说我的升级程序在生成文件列表时,给数字都以3个数字一段都加上了逗号,我狂晕!拿自己的debug代码试了试,发现果然如同事所言,看来是确定代码写得有问题了!  单步跟踪,最后发现我在把数字转换成字符串时,用了std::stringstream类的流输入方法,就变成那种样子了,稍微想了一下就明白过来了,以前一直都是没有逗号的,后来有过修改的地方也就是当时用ofstream写文件时,为了能支持中文的路径和文件名,在程序启动时调用了一句std::locale::global(std::locale(""));后来就有了这个问题。我狂分特啊,跟另外一个同事分享这个经验时,他还问我为什么不用boost::lexical_cast呢,其实据说boost::lexical_cast内部也是用的std::stringstream来转换的,哈哈!

总有一些自以为是的傻x

  说什么无法控制,说什么循环引用,说什么编译时间,都他妈的傻x。怎么不去关心一下CPU能不能控制,Windows能不能控制,还不是他妈的那儿老老实实用着。怎么不去用一下汇编,Fortran,狗日的哪来的循环引用。怎么不去用Debug自己输入二进制码,哪来的编译时间。  莫装B,装B被雷劈!

状态不好狂出错

  今天写代码,出了不少错,都是很低级的,状态不好啊。  先是连接一个MySQL数据库,从一个表中Select一些记录出来,死活没数据,还以为是SQL语句有问题,用其他客户端去运行,发现SQL语句是正常的。然后换了一条SQL语句,同样是Select的,发现又可以了,一步一步排查,发现是那个表中查不到数据,另外一个表中查得到数据,突然发现原来我连的MySQL地址不是我想要的那个!  接着是从XML格式的配置文件中读取配置信息,发现有的配置项好像怎么都读不出来,一直都是使用默认的值,后来才发现在判断值是否为空的时候,多写了个感叹号!  好不容易磕磕碰碰地调试通过了,编译了一个Release版本,用Inno Setup打了个包,放到目标机器上去运行,发现居然没反应,而且不巧的是我什么调试手段都没有,也没有什么日志。后来通过MessageBox发现,似乎配置信息读取又有问题了。然后发现如果是直接用Debug版本是正常的,于是想调试一下Release的,结果不知道应该设置什么选项,调试不了!只好通过OutputDebugString来打些信息出来。经过一番搏斗,发现原来我把装载配置文件的那条语句外面套了一个ASSERT,我狂晕!  以我现在的水平,状态好的时候,最多一个月也就能产1w行代码,而且代码质量还不能保证,唉,怎么才能让新写的代码跑得稳定呢!

准备使用Boost.Logging

  今天在Boost的邮件列表里看到有人在项目中使用Logging v2,这是在去年3月时提交Boost后review拒绝的一个库,当时我也略微关心过,因为一直在找一个好用的C++日志库,最后看到被拒绝了,我也就有点死心了,用起log4cxx来,其实发现log4cxx也不是那么好用,而且最近公司里用的时候发现似乎会有内存泄漏的问题。  看到邮件列表里那人对Logging的评价很高,我就心动了,它有一个优点是header only,这是我很喜欢的一点。其他的灵活性之类的我也没用过,也不好评价。不过我决定了,先在自己写的这些程序中试用一下。