[132期] 实战乃王道:C/C++开发常见bug解析

企业动态
程序员是个很辛苦的职业,通常面临无穷无尽的加班,但经过分析发现,大多数加班并不是因为项目时间不够,而是前期开发没有设计好,后期出现了无法跟踪,甚至无法解决的bug,导致研发时间不可控,这就是通常所说的“bug是加班之源”。

程序员是个很辛苦的职业,通常面临无穷无尽的加班,但经过分析发现,大多数加班并不是因为项目时间不够,而是前期开发没有设计好,后期出现了无法跟踪,甚至无法解决的bug,导致研发时间不可控,这就是通常所说的"bug是加班之源"。因此,我们如果能在设计阶段,预防、暴露很多bug,将大大减轻程序员的压力,使开发工作变得很愉快!

技术门诊是51CTO社区品牌栏目,每周邀请一位客座专家,为广大技术网友解答疑问。从热门技术到前沿知识,从技术答疑到职业规划。每期一个主题,站在最新最热的技术前沿为你引航!

本期技术门诊我们邀请到软件研发和管理领域专家、IT图书作者肖舸专家与大家讨论C/C++开发中的常见bug的解决方法。

本期专家:肖舸

擅长领域:C/C++,商用数据传输

专家简介:普罗通信(西安)有限公司研发主任,MCSE,商用程序员。拥有多年的软件研发和研发管理经验。精通C/C++,TCP/IP,擅长分布式数据库、服务器集群以及并行计算领域的研发。曾担任西南交大客座讲师,讲授《C/C++语言无错化程序设计》课程。曾在多家企业担任项目经理,负责过的项目有《http tunnel防火墙隧道穿越系统》、《freepp V1.5 服务器集群》、《电子白板子系统》等。 著有《0 Bug ---- C/C++商用工程之道》。

查看本期门诊精彩实录:http://doctor.51cto.com/develop-144.html

参与最新技术门诊:http://doctor.51cto.com/

精选本期网友提问与专家解答,以供网友学习参考。

Q:编辑程序一定要会英文吗

A:你好,我的理解,英文不是编程必须的,但是,英文好,无疑能极大地帮助编程开发。目前,国内的计算机书籍,普遍偏于肤浅,对于很多问题的深入讨论,开发人员一般习惯于看原版资料,另外,很多编程语言,平台api的开发说明,如VC的MSDN,Linux下的man等,都是英文原版的。这些都要求开发人员具有一定的英文功力。因此,建议尽量把英文学习好一点。

Q: 肖老师,您好! 一个困扰我很久的问题,我想问您一下:为什么creat()函数不是叫create()? 另外,O_CREAT标志为什么不叫O_CREATE?  这个算不算是一个bug?难道最初写这个函数的人不懂英文,以致于后来大家都跟着错,以致于像我这样按照正确的英文写函数名称的人会一再的写错这个函数的名字?

A:我的理解,这其实是一个人性化的问题。

英语发展到今天,其实已经不完全是英国人的英文了,其实世界各地的人们在使用英文过程中,其实都在按照自己本民族,本文化的习惯在修改英文。比如"颜色"这个词,colour,但是美国人嫌麻烦,就是不想写那个u,因此,慢慢地,这个词被修改为"color"了,最后英文本身也不得不认可这种修改。这中间例子还很多,比如"PK",比如"VS",都是人们在使用过程中,对英文的修订。这说明了语言一个很重要的特性,没有权威,用得人多了,自然就成了权威。

因此,学习英文要注意"方言",前段时间说中国人将会为英文贡献一些中国式英语,我觉得不难理解,也无可厚非,反正大多数人都这么用的话,就是对的。

你说的问题,可以理解为程序员的一种方言,程序员是很喜欢用缩写的,并且不是很讲究自然语法,开发英文更是不会去管时态等修饰变化,这些都是程序员特点,如果大家约定俗成,这么写也是无所谓,反正写的人和看得人都明白就好了。

不过,我个人还是喜欢使用create。呵呵。

Q:肖老师,您好!我想请教一个问题:

C++写插件报错,请问这个是bug么?

试了下用精灵source 文件夹下的QMPluginWizard.awx做dll,调试了很久终于成功编译成功, 结果放到plugin文件夹里面启动按键,正准备进脚本看看效果的时候弹出了上面的这个错误。开始还以为是我的函数问题,最后实在找不出错误,就不添加任何函数生成了一个原始的DLL ,结果一样报错=.=

请问这个问题是怎么回事呢……

A:sorry,你这个问题问得没头没尾的,我无法回答。

请问你在为什么系统写插件?PhotoShop,FireFox等很多软件,都有各自的插件体系,我不清楚你在写什么插件。简单说一点,插件就是软件的原始开发者自己定义一套api规约,允许后来的程序员使用这个api规约,开发属于自己的软件模块,原系统可以根据这个api规约予以调用,实现系统的扩容。因此,这首先是一个私有协议系统,不懂的人,水平再高也不会开发,因为它的定义都很随意,是原始程序员拍脑门的结果,另外呢,有一定规范性,必须按照人家约定的api规约来,不能有一点错误,否则就失败。建议你好好看看原始文档,体会需要提供的每一个api接口的特性,这样才能开发出正确的插件。

Q:肖老师您好!

软件测试的主要目的在于发现软件存在的错误(Bug),对于如何处理测试中发现的错误,将直接影响到测试的效果。只有正确、迅速、准确地处理这些错误,才能消除软件错误,保证要发布的软件符合需求设计的目标。在实际软件测试过程中,对于每个Bug都要经过测试、确认、修复、验证等的管理过程,这是软件测试的重要环节。相对来说,bug的管理也显得很重要了。

您能简单阐述一下Bug管理的一般流程吗?

A:我的理解,只要是软件企业,bug管理是必须的。bug管理抽象出来,是一个管理流程,和程序其实没有多大关系,而是公司里面有这么一套管理"人"的机制,以便对bug实行跟踪,落实到人头去解决。一般说来,公司内网应该安装一套bug管理系统,我们公司用的是Mantis,这是一个开源产品,很好用,根据权限,QA检查出bug,即提交到这个系统上,PM根据情况,指派给某个RD解决,解决后,RD回复已解决,并修改状态,QA做回归验证,最终实现一个闭环。我的理解,一般的测试人员,找到bug并不难,难的是如何精确描述bug,通常,QA对于bug的产生情况描述越精确,RD越能快速定位,快速解决。但这需要经验,不是每个人都能做到的。因此,我通常建议,bug的管理和解决,应该RD和QA共同努力,而不仅仅是测试部门的问题。我在开发中强调白盒测试,即RD写完每个模块,交稿时都要附有该模块的测试工程,这些测试代码不会最终release出去,但是,可以帮助PM和QA做初步的分模块验证,其实只要有这个验证过程,很多bug可以在RD提交代码之前解决的。

我的新书《0 Bug ---- C/C++商用工程之道》,其实主要就是一本RD写给RD的书籍,帮助RD养成良好的开发习惯,理解很多开发中细节的差异性,以便写出bug尽可能少的程序。这本身,就是试图从源头解决bug问题,降低后期QA的工作强度。

Q:系统2003,VC6.0编译时经常性死掉,只能结束任务,重新开启VC是不是有毛病呀?还是由于是盗版呀?

A:VS2003是一个中间版本,微软自己都承认有很多bug,建议换用VS2008。VC6.0还是比较稳定的,我用它开发过n个商用工程,应该问题不大。

关键是,如果你的程序中大量调用系统内核的资源,如共享内存区,锁,线程等机制,稍微控制不好,是可能把操作系统本身挂死的,因此,这个问题还是要反过来查找程序,如果程序中有bug,这就不是系统的毛病了,需要你作为程序员修改bug。我的新书《0 Bug ---- C/C++商用工程之道》,里面有几章着重论述了多任务开发中,内核访问的核心技术,如锁、内存、线程、任务等调度算法,并且给出了一个可用的工程库样例,建议书出来看一看,可以对操作系统内核的工作有个初步的理解。

Q:肖专家:

保存工具条菜单有 bug 吗?使用浮动菜单条时,SaveBarState 和 LoadBarState 出现了问题。如果菜单是浮动的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会出现在该位置,这是什么原因?

A:这个浮动工具条我用的比较少。嗯,初步分析,这个ocx控件有一定的自我状态存储机制,即退出时会保留自己当前的位置到注册表,下次启动后读入,并重新定位。如果你不想它自己保留,其实也很容易,简单说就是自己每次启动程序,主动用程序设置一下工具条的状态,把它放到你想放的地方就好了。

Q:肖老师,你好,可能提出的问题与这期主题不相关,自学C++有一段时间了.最近很迷茫,总感觉,知识很混乱,连不上来,而且自己一下觉的失去了目标,学了C++应该往哪一方面发展.如果自己是想向游戏这方面发展,应该如何走下去,以及在网上看到了有关游戏脚本语言,有些或惑,不太了解.

A:一般说来,写游戏还是需要用C和C++的,因为游戏讲究速度,脚本语言很难满足需求。如果你希望做游戏,现在的游戏公司一般都是网游居多,而且,游戏是典型的并行程序,对于多任务开发能力要求很高。建议看看DirectX开发相关书籍,嗯,我的书也可以看看,可以帮助提升多任务开发能力。

有机会的话,可以到游戏公司实习一下,就能更具体地了解需求了。

Q:肖老师您好:

我是一名刚刚学习C++的学生,我有几个问题想请教您,内容可能与本期主题无关。现在C++与JAVA语言,哪一个有更好的前途与"钱途"?学习完C++的语法知识后,还应该学一些什么呢?比如说是MFC之类的?对这个很迷茫!除了《C++编程思想》以外,还应该读一些什么好书呢?谢谢!

A:C++和Java很难说谁好谁坏,二者分别针对不同的领域。Java可能对于数据库应用,企业办公应用更合适一些,C++和C呢,则针对底层开发,高性能开发比较擅长。比如大型游戏,高性能服务器,嵌入式系统底层驱动等。我的理解,二者如果钻进去,都可以获得很好的钱途,不过,得钻才行。

我的博客中有几篇,对你可能有帮助,建议你看看。

关于Java转C++方向问题:

http://tonyxiaohome.blog.51cto.com/925273/198777

简述C和C++的学习历程:

http://tonyxiaohome.blog.51cto.com/925273/198753

关于C和C++找工作的讨论:

http://tonyxiaohome.blog.51cto.com/925273/198750

另外,如果你已经学习完C++的基本语法,建议看看我的新书《0 Bug ---- C/C++商用工程之道》,对于你迅速掌握C和C++开发的实战技巧,从学生走向程序员很有帮助。

Q:我刚学完C语言程序设计,要学C++,什么都不清楚,到底什么是bug,听说bug很严重,到底有多严重?听说编译环境也会影响程序的bug多少,是吗?到什么时候才应该注意bug,编写多大的程序才用的着查找bug?

A:bug是一种程序界的说法,其实就是指程序中的错误啦。理论上讲,任何程序都有错误,原因很简单,程序是人写的,是人就一定可能犯错误,这些错误,可能是简单的一个笔误,也可能是比较严重的逻辑歧义,逻辑冲突等,最终的结果都是一样,就是程序无法获得希望的设计结果。

其次,每个程序都有其应用范围,如果超出范围使用,也可能造成bug。比如我们设计一个服务器,预设为并发100用户服务,当并发用户增加到1000人时,就可能因为服务器太繁忙,而无法完成服务,这也是也是bug的一种。因此,bug是一个统称,其实包含了软件开发中各种各样的问题,只要不能达到或满足我们的设计要求,都可以算作bug。就程序而言,bug并不严重,因为只要bug暴露出来,程序员一般都有解决办法。严重的是商业程序涉及很多商务合同,有按期交工的时间底线,超过时限就罚款,甚至取消合同,这和钱有关系,就比较严重了。而如果不幸,我们发现软件运行有问题,并且bug找不到,就很严重了,程序员大量的加班都来自于此,并不是老板狠,而是商务合同快到期了,不拼命不行。因此,作为公司里面的商用开发来说,bug,特别是无法查找的bug,确实很严重。

理论上,软件研发的任何环节都有可能存在bug,不仅仅是代码实施阶段,在系统设计阶段,也可能存在bug,这往往会给软件后期的测试带来"硬伤",而这种"硬伤",成本往往很高昂。我亲身经历过的,就有由于系统基础库选型出现问题,最后软件工程差点失败,公司浪费人民币接近200万元的事情。因此,在软件研发的各个阶段,均应高度关注bug,再小的程序,也应该高度关注bug。商业程序员对很多bug要做到能预防,并且在软件开发中设置很多机制,帮助bug自行暴露,降低程序员查找bug的成本。

#p#

我的新书《0 Bug ---- C/C++商用工程之道》,里面详细介绍了我解决bug的方案《C/C++无错化程序设计方法》,其实这种方法并不是让程序真的没有bug,而是用很多习惯的养成,用很多统计、测量的方法,用程序帮助bug自动暴露出来,以便第一时间获得解决。因此,如果你以后希望开发高性能,高强度的商用程序,建议看看我的书,以后的程序开发工作,bug会比较少。

Q:c++与c有什么区别啊?

A: C++是面向对象开发,OO,C则是面向过程开发,OP。二者不同主要体现在开发思维上,所谓对象,就是一些数据,以及这些数据相关方法的组合,因此,C++的开发思想,主要体现在以数据为核心,并为数据搭配方法,而C的面向过程,则是以方法为核心,数据是方法处理的对象。

举个例子,我们把一个箱子搬上楼,C的说法,搬是一个方法,可以把箱子这个数据丢进去执行动作,最后出来的程序就是"搬(箱子)",而C++箱子是数据主题,搬是这个数据的方法,因此其说法变成了"箱子.搬()"。不过,二者其实区别也不是很大,C++毕竟脱胎于C,语法什么的都很接近,而且,即使是面向对象的C++,也是由一个个方法函数组成的,在每个函数内部,其实还是用面向过程的方法来写程序,因此,我一直有句话,学好C++,最好先学会C。就是这个道理。在我的新书《0 Bug ---- C/C++商用工程之道》里面,上述概念有更加详细的描述。另外,里面体现出来的实用化的开发思维,其实没有显式区分C和C++的概念,反而故意在混用二者进行开发,主要就是在解决实际工程问题时,随着各种问题的不同,有的适合用面向对象,有的适合用面向过程,单用哪种其实都不太好,合用最好用。因此,建议初学者不要太刻意去区分二者差异性,都学习一点比较好。

Q:你好,我是一个c++的初学者,我正在看的是《c++ primer》,请问你对初学者有什么建议?或者好的经验传授一下,谢谢。

A: 其实我的理解,《c++ primer》这本书挺好的,应该仔细看,多看,方能理解其中真意。当然,这本书主要是讲解C++本质,内核的一些东东,对于应用实战贴合不是很密切,因此,对于修炼内功。很有帮助,但是对于实战招式来说,还有所不足。我写过很多对初学者的建议,都在我的博客中,有兴趣的话,建议看看我博客的文章。http://tonyxiaohome.blog.51cto.com/ 另外,我的新书主要就是针对C和C++的实战做讲解,并进一步升华为原则和思想,建议等书出来,买本看看,会有好处的。

Q:肖老师,我在运行一段简单的代码的时候,出现了预想之外的结果:

1 /************************************************

2 * squares -- Print the squares of the numbers *

3 * from 1 to 5. *

4 ************************************************/

5 #include

6

7 int main()

8 {

9 // An array for the squares

10 int array[5];

11

12 int i; // Index into the array

13

14 for (i = 1; i <= 5; ++i) {

15 array[i] = i*i;

16 }

17

18 for (i = 1; i <= 5; ++i) {

19 std::cout << i << " squared is " <<

20 array[i] << '\n';

21 }

22 return (0);

23 }

请问,这种情况如何解释?这样的是程序设计中的bug吗?

A: 这段程序显然会崩溃的。

C和C++语言,都有个特点,就是数组的计数器是从0~n-1的,比如你的例子,int array[5];,则有效的数组单元是0,1,2,3,4,而你的循环体是从1~5,到最后一个数组时,已经超出了数组的界限,你去访问array[5]了,而这块内存显然不是分配给你的,你又做了赋值动作,相当于强行向一块不属于你的内存写入数据,因此,程序很可能因此而崩溃。

这是一个很重要的细节,在我的新书《0 Bug ---- C/C++商用工程之道》中,有一章专门讲解C和C++语言的无错化程序设计方法,中间特别有一节专门讲到了这个问题。即如何写for语句。标准的建议是:for(i=0;i

C和C++无错化程序设计方法,是通过一系列标准动作,标准写法,规避绝大多数常见bug的方法,建议书出来后看一看,这类问题以后就再也不会困扰你了。

Q:那么对于一个初学程序的人来说是 先学C语言好呢,还是先学VB 呢?或是其他语言!数据结构怎么学起啊?

A: 我觉得任何语言都可以入门,并且经过深入学习后,都可望成为大师。

C语言呢偏向底层,VB语言呢偏向Windows应用开发,特别是针对互联网和数据库方面,比较方便。看你自己的爱好和方向了。其他语言有Java,PHP,看看目前的语言排行榜,其实排前几位的就这几种,都可以学习的。数据结构则请跟着大学教材学习吧,这些知识比较死,也没什么发挥余地,教科书就是最好的参考书了。

Q:ntp技术是什么啊?

A:NTP协议全称网络时间协议(Network Time Procotol)。它的目的是在国际互联网上传递统一、标准的时间。具体的实现方案是在网络上指定若干时钟源网站,为用户提供授时服务,并且这些网站间应该能够相互比对,提高准确度。 NTP最早是由美国Delaware大学的Mills教授设计实现的,从1982件最初提出到现在已发展了将近20年,2001年最新的NTPv4精确度已经达到了200毫秒。

Q:您好,请问您,如何在设计阶段预防无效的不必要的加班,从而减轻程序员的压力!谢谢您!

A: 你的这个问题有点"大",不是一句两句话能说清楚的。我们知道,软件应对的应用场合很多,不同的项目类型,侧重点各有不同,因此,很难有一个通理能解决所有的问题。简单说的话,我的理解,系统设计有个问题必须要解决,就是回答好"市场要什么"和"我们能做什么"这两个问题之间的矛盾。

我们知道,尺有所短,寸有所长,任何一个公司的研发部门,任何一个高手程序员,都不敢说,自己的知识领域,能够覆盖所有的应用需求,因此,每次当市场需求反馈到研发部门,我们都需要做个评估,到底能完成哪些部分。这并不丢人,而是一种务实的解决问题的态度。因此,公司的系统设计师,其实应该善于把握平衡,并不是市场说的都对,也不是研发说的就一定做不到,而是在市场和研发之间维持一种平衡,针对市场需求,为研发设置一个稍微高一点的目标,跳一下就能够到,不是研发天天躺在过去的成绩上睡大觉,这样做的产品肯定没法卖,也不应该怎么跳都够不到,研发逼死都做不出来,那最终还是市场没有可卖的产品。

其实这对系统架构师,设计师这个角度来说,要求非常高,既要有敏锐的市场分析能力,能对市场需求去伪存真,提取那些可做到的,成本本公司能承受,市场上又确实有突出卖点的功能点来做,又要对本公司研发团队能力有很详细的了解,知道研发的底线在哪里,不会一味讨好市场和老板,设置一些根本不可能达成的目标。现代企业中,一般不是一个人做这件事,而是几个专家组成工作组来共同完成,他们小范围的PK,能极大节约公司市场部和研发部之间的大量沟通成本。

另外,在项目管理的各个关键点,设置里程碑,实施各级评审也能较好地解决上述矛盾。很多公司为了解决上述矛盾,甚至专门开预研类项目,来对某个新技术做预研和技术储备,以便更好地指导下一步的研发工作。上述细节看似和研发没有关系,但可以看出,如果上述工作做好了,关键技术点都有了成熟解决方案,并且,产品路线图做得很合理,一步步地前进,则可望做到设计阶段预防无效的,不必要的加班,从而减轻程序员的压力。当然,这个问题是一个系统工程,需要全公司从机构设置,工作流程安排上作出努力,才可望做到。

作为程序员呢,其实也可以在其中做一点工作,我们知道,一个公司做的事情,主要还是针对有限的几个方面,不同的产品和项目,技术上总得来说还是有传承性,比如做路由器的厂商,可能在嵌入式系统底层的一些模块有技术积累,而做网游的厂商,则对图形处理部分肯定有积累。程序员我认为有责任把这种积累变成"工程库",每次新技术的开发,都尽快以工程库的形式沉淀下来,才能避免二次重复开发,并且,经过长期积淀的工程库,往往经过了多个工程的测试验证,性能很稳定,bug很少甚至没有,这样新工程依托这些成熟稳定的工程库,就可望快速成型,且质量稳定,由此也会避免程序员大量无谓的加班找bug的过程。

并且,工程库的整理和维护,也可以使系统分析员对本公司技术实力有个更加清晰的认识,对于未来项目设计更加具有合理性,因此,从这个意义上说,即使是刚刚加入公司的程序员,对于系统设计的仍然是有互动作用的,就是及时总结和归纳自己已经做过的程序段落,及时形成自己的工程库,并争取纳入公司级的工程库做一体化维护,这才是软件开发中,减少bug,降低开发劳动量,避免无谓加班的终极解决之道。

我的新书《0 Bug ---- C/C++商用工程之道》,主要目的就是站在商用工程开发的角度,帮助大家建立工程库思想,并提供一个初步的多线程安全工程库供大家使用。因此,这本书对于你的问题有很大的帮助,建议等11月份书出来后,买本来参考。

【编辑推荐】

  1. C/C++中Static的作用详述
  2. Google App Engine Python SDK 1.2.7 bug升级
  3. 在C/C++算法设计中使用任意位宽
责任编辑:张攀 来源: 51cto
相关推荐

2011-07-14 17:45:06

CC++

2011-04-11 09:43:25

C++C

2024-04-03 12:30:00

C++开发

2012-08-03 08:57:37

C++

2021-09-23 14:41:58

鸿蒙HarmonyOS应用

2024-02-21 14:55:19

C++语言编程

2010-01-15 17:38:37

C++语言

2010-01-28 10:33:10

C++开发程序

2010-01-25 18:24:11

C++

2010-01-21 11:23:58

C++函数调用

2010-01-27 10:22:53

C++基类

2024-04-02 09:35:27

开发C++

2010-01-22 16:35:41

C++开发

2020-12-30 10:38:54

漏洞编程语言加密

2023-12-06 13:48:00

C++代码

2010-02-01 16:40:14

C++枚举子

2010-02-05 12:57:20

C++ kdevelo

2010-01-28 13:15:43

C++参数

2023-11-09 23:31:02

C++函数调用

2010-02-02 16:15:38

C++变量声明
点赞
收藏

51CTO技术栈公众号