2012年8月5日星期日

一次悲催的Debug经历

今天终于搞定了困扰我两天之久的一个令程序崩溃的bug,不过这个bug着实让我汗颜。
不多说,上代码。


enum MotionDirection{UP_RIGHT = 1,DOWN_LEFT,UP_LEFT,DOWN_RIGHT,
                     HORIZONTAL_LEFT,HORIZONTAL_RIGHT,
                    VERTICAL_UP,VERTICAL_DOWN};

void OpticalFlow::tracking(cv::Mat &frame, cv::Mat &output, std::vector<float> &wp)
{
...
float velocity[8] = {0.0};//8个方向的速度
int flags[8] = {0};//8个方向出现的次数
uint i = 0;
while( i < workingSet.size()) {
int pos = getOldVectorPos(workingSet[i],points[0]);
if(pos != NO_APPLICABLE_POINT_FOUND)
//计算当前特征点的方向和速度信息
countDirectionAndSpeed(workingSet[i],pos,velocity,flags);
++i;
}
...
//为下一帧跟踪初始化特征点集和灰度图像
std::swap(points[1], points[0]);
cv::swap(gray_prev, gray);
}
     这段代码的主要作用是进行人数统计和运动方向检测,但是每次程序运行都会崩溃。Debug设断点跟踪竟然是cv::swap(gray_prev,gray)引起的,其执行完后就会引发错误。然而这个函数是比我有经验的多的程序员写的,应该不会有问题。于是苦逼的继续调试,大约两个小时后,终于看到原来枚举变量MotionDirection的值是从1开始的,而我定义的两个数组velocity和flags下标都是从0开始,因此会造成越界的问题!
     想到这里,将上述定义改为
         float velocity[9] = {0.0};//8个方向的速度,第0位不用
         int flags[9] = {0};//8个方向出现的次数
     问题解决了。
总结:
     虽然是很小的一个问题,却让我认识到两方面的内容。其一,要相信库函数,除非有充分的证据。出问题先从自身找原因;其二,越界和粗心大意的写代码仍是我写的代码的主要崩溃手段。
     就这么多吧。最后送福利图一枚:,来自爱软。

2012年7月31日星期二

Warning: Z-order assignment: " is not a valid widget. 的解决办法

    在Qt Creator中使用可视化方式设置用户界面时,如果过多地进行了添加删除操作以及频繁的添加、删除及更改布局(本人就是这样遇到此问题的,非官方正式解释),便有可能在编译代码时出现上述警告。虽说是警告,但是前面是用代表错误的红点来表示的,看起来令人颇为不爽。好在神奇的stackoverflow总是能给我们惊喜。这个帖子下方的回答告诉了我们该怎么做。没兴趣跳转的同学,下面是解决方法:
    用Vim打开.ui文件,删除所有<z-order>值为空的标签,保存后再编译就没问题了。
    向提供此方法的Vlad致敬!如果Up Vote没有限制,我会顶他10次。
    最后是福利图,转自爱软


2012年7月19日星期四

论孙老师的走掉


孙老师最近在其博客中发布了一篇博文,总结了前生,展望了来世,顺便提及了很重要的一点:哥要走了。
       印象中和孙老师的接触起源于大三的操作系统。这也是我唯一一门90分以上的专业课,也是唯一一门认真学习过的课程;另一门90分的课是体育。以后我可以自豪的说,我的体育是操作系统老师教的【1】。我想,我会认真学习这门课并进而对计算机产生兴趣,完全在于孙老师和李老师的课程改革,将死板的条条框框融入到日常实践中去。孙老师确实有化腐朽为棒槌的能力。然而如今,他要走了。
       孙老师是一朵自由行走的花,我们都不懂他。
       刚看到此文以为孙老师喝多了,但是看下去后,慢慢觉得这才是一个真正爷们应该做的。按孙老师的说法,10年来,当初和孙老师一起出道的同事,现在有多少多少博导,有多少多少教授,而孙老师刚评为副教授,看似无所作为。但是那些博导和教授,现在可能已经没有多少人记得当初为什么投身教育行业了,每天所想只是项目和经费——当然,这么说肯定片面和极端。而工大的学生们,又有多少人知道和了解这些老师们呢?这些老师们还有多少心里装着学生呢?然而,只要在工大,提起孙老师的名号,无人不挑大拇哥。XXX教授?没听过,不认识;孙志岗老师?哦,就是那个会教体育的操作系统老师,知道知道!以至于在工大,一个有觉悟的学生,不管他来到哪个国家,不管命运把他抛到哪里,不管他怎样感到自己是个异邦人,言语不通,举目无亲,远离祖国,——他都可以凭着“孙志岗”这熟悉的名字,给自己找到同志和朋友【2】。 
       10年来孙老师是为了自己的理想而教学,而不是为了功名利禄。可以说,乐学网就是最好的例子。孙老师在缺医少药几近弹尽粮绝的情况下硬是把乐学网打造成了一个在线教育及互动平台,这不是每个人都可以做的到的。如果没有强大的精神支柱和“一颗足够强大的心脏”,乐学网早就404了。鲁迅先生在《论雷峰塔的倒掉》中,将雷峰塔倒掉的社会新闻与《白蛇传》的民间故事巧妙地结合起来,借雷峰塔的倒掉,赞扬了白娘娘为争取自由和幸福而决战到底的反抗精神,揭露了封建统治阶级镇压人民的残酷本质,鞭鞑了那些封建礼教的卫道者,从而表达了人民对“镇压之塔”倒掉的无比欢欣的心情【3】。
       孙老师以35之龄放弃了事业单位的铁饭碗,投身互联网公司的大潮,这需要非常大的勇气和毅力,以及足够的说服能力,特别是在当前中国经济保八失败以及IT从业者(码农、码畜)不断猝死的不利情形下【4】。从原文中可以看出,孙老师一直在身体力行"Follw your heart"——中文有个奇妙的字:怂——的价值观,为自己而活。告别安稳的生活,追逐未知的未来。孙老师似乎化身为追风少年奔向远方,只为我们留下一道靓丽的背影和一丝略带猥琐的微笑。我等众生唯有报以敬仰的目光目送其前进,却惟独无法追随其脚步,我们活得太累了。孙老师的离开,并不包含“此处不留爷,自有留爷处”的无奈与悲凉,更多的是投身互联网大潮争做弄潮儿的雄心与壮志。
       被猴子袭击失去讲稿的得道高僧延参法师曾经说过:让绳命多一些开心,让岁月剁一些回晃,让人生剁一些井猜,让生命剁一些井猜。壤窝们,巩痛嘱咐碰优。田下冯广宰饿妹,饿妹冯广宰呲处。壤窝们,嘱咐这缩优类缩优。开心的一小,火大的一小,壤绳命,梗楤容,壤绳命,梗秤巩,壤绳命,梗回晃【5】。 正是因为有这些不安于现状勇于攀登的人们,我们的“绳命”才能如此从容,我们的世界才能如此井猜。祝孙老师以后不论遇到什么艰难险阻,都能够微微一笑化险为夷;祝孙老师以后能继续坚持自己的理想;最后,希望孙老师能有时间继续更新"Hello World"
       最后一次叫您一声孙老师。下次见面,就是孙经理了。
注解:
【1】:改编自“你的数学是体育老师教的吧”。
【2】:改编自列宁纪念《国际歌》的作者欧仁•鲍狄埃的文章里的一段话。
【3】:看着似乎毫无头绪?其实隐晦的表达了对学校不作为和山寨乐学网的一种不满,来自百度百科。
【4】:唉,注意身体吧骚年们!
【5】:引用网友调戏谷歌娘的段子。

2012年6月24日星期日

在Qt4.8.0中使用OpenCV 2.3程序异常退出的解决办法

      最近要做一些视频处理方面的内容,在Directshow和OpenCV之间徘徊了一阵后选择了OpenCV,毕竟和Qt一样都是开源跨平台的东东,搭配在一起显得格外和谐。然而按照这篇教程写完后发现那位博主使用的是OpenCV 2.1,而我下载的是OpenCV 2.3,似乎目录结构发生了一些变化,不能按照原来的方法写.pro文件了。琢磨了一番后将文件修改如下:

#-------------------------------------------------
#
# Project created by QtCreator 2012-06-23T15:40:59
#
#-------------------------------------------------
QT       += core gui
TARGET = opencv
TEMPLATE = app

SOURCES += main.cpp\
        mainwindow.cpp
HEADERS  += mainwindow.h
FORMS    += mainwindow.ui
INCLUDEPATH += F:/opencv/build/include
INCLUDEPATH += F:/opencv/build/include/opencv
LIBS += F:\OpenCV2.3\build\x86\mingw\bin\*.dll
      编译没问题,结果运行的时候程序直接退出了,返回值-1073741515。一开始以为是.pro文件的问题,可是无论怎么修改仍然是不能正常运行;更换2.4.1版本的程序库也无济于事。在此期间甚至想放弃Qt转投VS(按照网上的教程VS 2010配置运行成功)。在绝望的时候,突然想会不会是缺什么东西的原因。因此在资源管理器中将所需全部DLL文件复制到exe程序目录下,点击运行后,系统果然提示缺少libstdc++-6.dll这个文件,不仅喜上眉梢,有门!
         然而此时高兴为时太早。将C:\QtSDK\mingw\bin下的libstdc++-6.dll复制过来后却提示“无法定位程序输入点”,看来DLL版本不对!只能上网搜碰运气了!终于,在这里找到了合适的DLL,这回终于正常运行了!
         老规矩,再次放上福利图一枚(看着是不是有点眼熟呢?):



2012年4月5日星期四

++++i和i++++的蛋疼问题

从标题就可以看出这个问题有多蛋疼了。平时谁会这么用啊啊啊啊!!!
不过,既然是个问题,总要有个答案,否则岂不抱憾终生?
通过google,在stackoverflow上寻到了答案

​T& operator ++(T& a);​     // pre
​T operator ++(T& a, int);​ // post
                          // note the int is solely to distinguish the two
也就是说,i++返回的是变量的值,++i返回的是变量的引用。因此i++++就相当于一个常数++,当然编译是没法通过的,而++++i就可以顺利通过。
但是,根据这个帖子,这两种表达式都会引发“未定义的行为”,因此“Don't do either of them.”
现在没什么遗憾了,这就是“朝闻道,夕死可以”的境界。
最后附上福利美图一枚。



2012年3月24日星期六

U盘FAT32、NTFS格式速度比较

最近用U盘安装Fedora 16,结果安装后无法启动T_T。没辙,U盘还得用啊。可是发现速度降低了不少,原来写入速度可以到5M,现在只有4M左右。想起来格式化时选择的参数是FAT32、块大小4096字节。于是希望缓缓参数来改变速度。于是取不同的分区和块大小分别进行测试。
FAT32分区、块大小4096字节

FAT32分区、块大小8192字节

NTFS分区、块大小16KB


NTFS分区、块大小8192字节
可以看出,块大小为8KB时相比4KB具有很大优势,而块大小为16KB时速度反而下降,而且空间浪费也较大。同时对于8G大小的U盘,有时需要装大于4G的文件,因此选择NTFS格式,块大小为8192字节是最为合适的,可以在速度和空间方面取得平衡。
最后上一张写入速度图:

2012年3月8日星期四

Qt 4.8.0中QAxWidget代码编译不通过的解决办法

    昨天在QtCN上看到Qt的4.8.0版本已发布的消息,决定升级之。QTSDK的升级工具照旧极度不给力(下载太慢了),于是用迅雷以10M/S的速度下载完成后离线安装。安装过程一切正常,但是编译测试以前写的一个QAxWidget项目时出现错误,提示C:\QtSDK\Desktop\Qt\4.8.0\mingw\include\ActiveQt\qaxwidget.h这个文件中所包含的文件不存在,其内容只有一句:#include "../../src/activeqt/container/qaxwidget.h"。其需要在C:\QtSDK\Desktop\Qt\4.8.0\mingw目录下存在src子目录,但是我的Qt安装后并没有这个目录,而4.7.4版本就没有这个问题。

  •    通过SDK升级工具下载安装了QT Sources源码包。此时在QtSDK目录下多出来了一个QtSources文件夹,里面有我们所需的src目录。将其剪切至上述目录后,这回可以编译了。

   但是链接的时候却提示cannot find -lQAxContainerd。大意是在C:\QtSDK\Desktop\Qt\4.8.0\mingw\lib目录下缺少libQAxContainerd.a这个库文件。

  •  因此用QtCreator打开C:\QtSDK\Desktop\Qt\4.8.0\mingw\src\activeqt\activeqt.pro工程,以Debug方式编译后即可生成libQAxContainerd.a库文件(以Release方式生成libQAxContainer.a),复制到C:\QtSDK\Desktop\Qt\4.8.0\mingw\lib,再次编译却出现"Undefiened reference to __SomeFunc@8",这回无解了。

   正在悲伤之际,突然发现了这篇文章,简直如获至宝。大意是说4.8.0有问题,不能使用MingW编译,要使用VS才行。

  • 幸亏安装了VS2010,在左下角点击“计算机”图标后选择VS-调试后再次编译,终于搞定。


   感谢国家,感谢党,感谢谷歌。