函数无法定位程序输入点于动态链接库

无法定位程序输入点于动态链接库  时间:2021-03-01  阅读:()
目录1排版62注释113标识符命名184可读性205变量、结构226函数、过程287可测性368程序效率409质量保证4410代码编辑、编译、审查5011代码测试、维护5212宏53软件编程规范总则1排版1排版1-1:程序块要采用缩进风格编写,缩进的空格数为4个.
说明:对于由开发工具自动生成的代码可以有不一致.
1-2:相对独立的程序块之间、变量说明之后必须加空行.
示例:如下例子不符合规范.
if(!
valid_ni(ni)){.
.
.
//programcode}repssn_ind=ssn_data[index].
repssn_index;repssn_ni=ssn_data[index].
ni;应如下书写if(!
valid_ni(ni)){.
.
.
//programcode}repssn_ind=ssn_data[index].
repssn_index;repssn_ni=ssn_data[index].
ni;1-3:较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读.
示例:perm_count_msg.
head.
len=NO7_TO_STAT_PERM_COUNT_LEN+STAT_SIZE_PER_FRAM*sizeof(_UL);act_task_table[frame_id*STAT_TASK_CHECK_NUMBER+index].
occupied=stat_poi[index].
occupied;act_task_table[taskno].
duration_true_or_false=SYS_get_sccp_statistic_state(stat_item);report_or_not_flag=((taskno),后不应加空格.
说明:采用这种松散方式编写代码的目的是使代码更加清晰.
由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在C/C++语言中括号已经是最清晰的标志了.
在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格.
给操作符留空格时不要连续留两个以上空格.
示例:(1)逗号、分号只在后面加空格.
inta,b,c;仅供内部使用6软件编程规范总则1排版(2)比较操作符,赋值操作符"算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符"=MAX_TIME_VALUE)a=b+c;a*=2;a=b^2;(3)地址运算符)等单目操作符前后不加空格.
*p='a';//内容操作"*"与内容之间flag=!
isEmpty;//非操作"!
"与内容之间p=&mem;//地址操作"&"与内容之间i+与内容之间(4)前后不加空格.
p->id=pid;指针前后不加空格(5)if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显.
if(a>=b&&c>d)1-1:一行程序以小于80字符为宜,不要写得过长.
仅供内部使用7软件编程规范总则2注释2注释2-1:一般情况下,源程序有效注释量必须在20%以上.
说明:注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁.
2-2:说明性文件(如头文件.
h文件、.
inc文件、.
def文件、编译说明文件.
cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明.
示例:下面这段头文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内.
Copyright(C),1988-1999,HuaweiTech.
Co.
,Ltd.
Filename://文件名Author:Version:Date://作者、版本及完成日期Description://用于详细说明此程序文件完成的主要功能,与其他模块//或函数的接口,输出值、取值范围、含义及参数间的控//制、顺序、独立或依赖等关系Others://其它内容的说明FunctionList://主要函数列表,每条记录应包括函数名及功能简要说明1.
.
.
.
.
History://修改历史记录列表,每条修改记录应包括修改日期、修改//者及修改内容简述1.
Date:Author:Modification:2.
.
.
.
2-3:源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等.
示例:下面这段源文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内.
仅供内部使用8软件编程规范总则2注释Copyright(C),1988-1999,HuaweiTech.
Co.
,Ltd.
FileName:test.
cppAuthor:Version:Date:Description://模块描述Version://版本信息FunctionList://主要函数及其功能1.
History://历史修改记录David96/10/121.
0buildthismoudle说明:Description一项描述本文件的内容、功能、内部各部分之间的关系及本文件与其它文件关系等.
History是修改历史记录列表,每条修改记录应包括修改日期、修改者及修改内容简述.
2-4:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等.
示例:下面这段函数的注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内.
Function://函数名称Description://函数功能、性能等的描述Calls://被本函数调用的函数清单CalledBy://调用本函数的函数清单TableAccessed://被访问的表(此项仅对于牵扯到数据库操作的程序)TableUpdated://被修改的表(此项仅对于牵扯到数据库操作的程序)Input://输入参数说明,包括每个参数的作//用、取值说明及参数间关系.
Output://对输出参数的说明.
Return://函数返回值的说明Others://其它说明仅供内部使用9软件编程规范总则2注释2-5:边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性.
不再有用的注释要删除.
2-6:注释的内容要清楚、明了,含义准确,防止注释二义性.
说明:错误的注释不但无益反而有害.
规则2-7:避免在注释中使用缩写,特别是非常用缩写.
说明:在使用缩写时或之前,应对缩写进行必要的说明.
2-8:注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开.
示例:如下例子不符合规范.
例1:/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].
repssn_index;repssn_ni=ssn_data[index].
ni;例2:repssn_ind=ssn_data[index].
repssn_index;repssn_ni=ssn_data[index].
ni;/*getreplicatesubsystemindexandnetindicator*/应如下书写/*getreplicatesubsystemindexandnetindicator*/repssn_ind=ssn_data[index].
repssn_index;repssn_ni=ssn_data[index].
ni;2-9:对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义.
变量、常量、宏的注释应放在其上方相邻位置或右方.
示例:/*activestatistictasknumber*/#defineMAX_ACT_TASK_NUMBER1000仅供内部使用10软件编程规范总则2注释#defineMAX_ACT_TASK_NUMBER1000/*activestatistictasknumber*/2-10:数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释.
对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方.
示例:可按如下形式说明枚举/数据/联合结构.
/*sccpinterfacewithsccpuserprimitivemessagename*/enumSCCP_USER_PRIMITIVE{N_UNITDATA_IND,/*sccpnotifysccpuserunitdatacome*/N_NOTICE_IND,/*sccpnotifyusertheNo.
7networkcannot*//*transmissionthismessage*/N_UNITDATA_REQ,/*sccpuser'sunitdatatransmissionrequest*/};2-11:全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明.
示例:/*TheErrorCodewhenSCCPtranslate*//*GlobalTitlefailure,asfollows*///变量作用、含义/*0-SUCCESS1-GTTableerror*//*2-GTerrorOthers-nouse*///变量取值范围/*onlyfunctionSCCPTranslate()in*//*thismodualcanmodifyit,andother*//*modulecanvisititthroughcall*//*thefunctionGetGTTransErrorCode(使用方法BYTEg_GTTranErrorCode;2-12:注释与所描述内容进行同样的缩排.
说明:可使程序排版整齐,并方便注释的阅读与理解.
示例:如下例子,排版不整齐,阅读稍感不方便.
voidexample_fun(void){/*codeonecomments*/CodeBlockOne仅供内部使用11软件编程规范总则2注释/*codetwocomments*/CodeBlockTwo}应改为如下布局.
voidexample_fun(void){/*codeonecomments*/CodeBlockOne/*codetwocomments*/CodeBlockTwo}2-13:将注释与其上面的代码用空行隔开.
示例:如下例子,显得代码过于紧凑.
/*codeonecomments*/programcodeone/*codetwocomments*/programcodetwo应如下书写/*codeonecomments*/programcodeone/*codetwocomments*/programcodetwo2-14:对变量的定义和分支语句(条件分支、循环语句等)必须编写注释.
说明:这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档.
2-15:对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释.
说明:这样比较清楚程序编写者的意图,有效防止无故遗漏break语句.
仅供内部使用12软件编程规范总则2注释示例(注意斜体加粗部分):caseCMD_UP:ProcessUp();break;caseCMD_DOWN:ProcessDown();break;caseCMD_FWD:ProcessFwd();if(.
.
.
){.
.
.
break;}else{ProcessCFW_B();//nowjumpintocaseCMD_A}caseCMD_A:ProcessA();break;caseCMD_B:ProcessB();break;caseCMD_C:ProcessC();break;caseCMD_D:ProcessD();仅供内部使用13软件编程规范总则2注释break;.
.
.
2-1:避免在一行代码或表达式的中间插入注释.
说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差.
2-2:通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的.
说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释.
2-3:在代码的功能、意图层次上进行注释,提供有用、额外的信息.
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息.
示例:如下注释意义不大.
/*ifreceive_flagisTRUE*/if(receive_flag)而如下的注释则给出了额外有用的信息.
/*ifmtpreceiveamessagefromlinks*/if(receive_flag)2-4:在程序块的结束行右方加注释标记,以表明某程序块的结束.
说明:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读.
示例:参见如下例子.
if(.
.
.
){//programcodewhile(indexb)a:b;改为如下就很清晰了.
intmax(inta,intb){return((a>b)a:b);}value=max(a,b);或改为如下.
#defineMAX(a,b)(((a)>(b))(a):(b))value=MAX(a,b);仅供内部使用30软件编程规范总则6函数、过程6-5:不要设计多用途面面俱到的函数.
说明:多功能集于一身的函数,很可能使函数的理解、测试、维护等变得困难.
6-6:函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出.
说明:带有内部"存储器"的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态.
这样的函数既不易于理解又不利于测试和维护.
在C/C++语言中,函数的static局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是STATIC的局部变量的地址作为返回值,若为AUTO类,则返回为错针.
示例:如下函数,其返回值(即功能)是不可预测的.
unsignedintinteger_sum(unsignedintbase){unsignedintindex;staticunsignedintsum=0;//注意,是static类型的.
//若改为auto类型,则函数即变为可预测.
for(index=1;indexB->C->A),影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间);递归调用对程序的测试有一定影响.
故除非为某些算法或功能的实现方便,应减少没必要的递归调用.
6-25:仔细分析模块的功能及性能需求,并进一步细分,同时若有必要画出有关数据流图,据此来进行模块的函数划分与组织.
说明:函数的划分与组织是模块的实现过程中很关键的步骤,如何划分出合理的函数结构,关系到模块的最终效率和可维护性、可测性等.
根据模块的功能图或/及数据流图映射出仅供内部使用35软件编程规范总则6函数、过程函数结构是常用方法之一.
6-26:改进模块中函数的结构,降低函数间的耦合度,并提高函数的独立性以及代码可读性、效率和可维护性.
优化函数结构时,要遵守以下原则:(1)不能影响模块功能的实现.
(2)仔细考查模块或函数出错处理及模块的性能要求并进行完善.
(3)通过分解或合并函数来改进软件结构.
(4)考查函数的规模,过大的要进行分解.
(5)降低函数间接口的复杂度.
(6)不同层次的函数调用要有较合理的扇入、扇出.
(7)函数功能应可预测.
(8)提高函数内聚.
(单一功能的函数内聚最高)说明:对初步划分后的函数结构应进行改进、优化,使之更为合理.
6-27:在多任务操作系统的环境下编程,要注意函数可重入性的构造.
说明:可重入性是指函数可以被多个任务进程调用.
在多任务操作系统中,函数是否具有可重入性是非常重要的,因为这是多个进程可以共用此函数的必要条件.
另外,编译器是否提供可重入函数库,与它所服务的操作系统有关,只有操作系统是多任务时,编译器才有可能提供可重入函数库.
如DOS下BC和MSC等就不具备可重入函数库,因为DOS是单用户单任务操作系统.
6-28:避免使用BOOL参数.
说明:原因有二,其一是BOOL参数值无意义,TURE/FALSE的含义是非常模糊的,在调用时很难知道该参数到底传达的是什么意思;其二是BOOL参数值不利于扩充.
还有NULL也是一个无意义的单词.
6-29:对于提供了返回值的函数,在引用时最好使用其返回值.
6-30:当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替.
说明:这样可以增加编程效率和程序的可读性.
示例:在某过程中较多引用TheReceiveBuffer[FirstSocket].
byDataPtr,则可以通过以下宏定义来代替:#definepSOCKDATATheReceiveBuffer[FirstScoket].
byDataPtr仅供内部使用36软件编程规范总则7可测性7可测性7-1:在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明.
说明:本规则是针对项目组或产品组的.
7-2:在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式.
信息串中至少要有所在模块名(或源文件名)及行号.
说明:统一的调测信息格式便于集成测试.
7-3:编程的同时要为单元测试选择恰当的测试点,并仔细构造测试代码、测试用例,同时给出明确的注释说明.
测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关).
说明:为单元测试而准备.
7-4:在进行集成测试/系统联调之前,要构造好测试环境、测试项目及测试用例,同时仔细分析并优化测试用例,以提高测试效率.
说明:好的测试用例应尽可能模拟出程序所遇到的边界值、各种复杂环境及一些极端情况等.
7-5:使用断言来发现软件问题,提高代码可测性.
说明:断言是对某种假设条件进行检查(可理解为若条件成立则无动作,否则应报告),它可以快速发现并定位软件问题,同时对系统错误进行自动报警.
断言可以对在系统中隐藏很深,用其它手段极难发现的问题进行定位,从而缩短软件问题定位时间,提高系统的可测性.
实际应用时,可根据具体情况灵活地设计断言.
示例:下面是C语言中的一个断言,用宏来设计的.
(其中NULL为0L)#ifdef_EXAM_ASSERT_TEST_//若使用断言测试voidexam_assert(char*file_name,unsignedintline_no){printf("\n[EXAM]Assertfailed:%s,line%u\n",file_name,line_no);abort();仅供内部使用37软件编程规范总则7可测性}#defineEXAM_ASSERT(condition)if(condition)//若条件成立,则无动作NULL;else//否则报告exam_assert(__FILE__,__LINE__)#else//若不使用断言测试#defineEXAM_ASSERT(condition)NULL#endif/*endofASSERT*/7-6:用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况.
7-7:不能用断言来检查最终产品肯定会出现且必须处理的错误情况.
说明:断言是用来处理不应该发生的错误情况的,对于可能会发生的且必须处理的情况要写防错程序,而不是断言.
如某模块收到其它模块或链路上的消息后,要对消息的合理性进行检查,此过程为正常的错误检查,不能用断言来实现.
7-8:对较复杂的断言加上明确的注释.
说明:为复杂的断言加注释,可澄清断言含义并减少不必要的误用.
7-9:用断言确认函数的参数.
示例:假设某函数参数中有一个指针,那么使用指针前可对它检查,如下.
intexam_fun(unsignedchar*str){EXAM_ASSERT(str!
=NULL);//用断言检查"假设指针不为空"这个条件.
.
.
//otherprogramcode}7-10:用断言保证没有定义的特性或功能不被使用.
示例:假设某通信模块在设计时,准备提供"无连接"和"连接"这两种业务.
但当前的版本中仅实现了"无连接"业务,且在此版本的正式发行版中,用户(上层模块)不应仅供内部使用38软件编程规范总则7可测性产生"连接"业务的请求,那么在测试时可用断言检查用户是否使用"连接"业务.
如下.
#defineEXAM_CONNECTIONLESS0//无连接业务#defineEXAM_CONNECTION1//连接业务intmsg_process(EXAM_MESSAGE*msg){unsignedcharservice;/*messageserviceclass*/EXAM_ASSERT(msg!
=NULL);service=get_msg_service_class(msg);EXAM_ASSERT(service!
=EXAM_CONNECTION);//假设不使用连接业务.
.
.
//otherprogramcode}7-11:用断言对程序开发环境(OS/Compiler/Hardware)的假设进行检查.
说明:程序运行时所需的软硬件环境及配置要求,不能用断言来检查,而必须由一段专门代码处理.
用断言仅可对程序开发环境中的假设及所配置的某版本软硬件是否具有某种功能的假设进行检查.
如某网卡是否在系统运行环境中配置了,应由程序中正式代码来检查;而此网卡是否具有某设想的功能,则可由断言来检查.
对编译器提供的功能及特性假设可用断言检查,原因是软件最终产品(即运行代码或机器码)与编译器已没有任何直接关系,即软件运行过程中(注意不是编译过程中)不会也不应该对编译器的功能提出任何需求.
示例:用断言检查编译器的int型数据占用的内存空间是否为2,如下.
EXAM_ASSERT(sizeof(int)==2);7-12:正式软件产品中应把断言及其它调测代码去掉(即把有关的调测开关关掉).
说明:加快软件运行速度.
7-13:在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响.
说明:即有测试代码的软件和关掉测试代码的软件,在功能行为上应一致.
7-14:用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本仅供内部使用39软件编程规范总则7可测性的不同源文件,以减少维护的难度.
7-15:软件的DEBUG版本和发行版本应该统一维护,不允许分家,并且要时刻注意保证两个版本在实现功能上的一致性.
7-1:在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码如打印函数等.
说明:程序的调试与测试是软件生存周期中很重要的一个阶段,如何对软件进行较全面、高率的测试并尽可能地找出软件中的错误就成为很关键的问题.
因此在编写源代码之前,除了要有一套比较完善的测试计划外,还应设计出一系列代码测试手段,为单元测试、集成测试及系统联调提供方便.
7-2:调测开关应分为不同级别和类型.
说明:调测开关的设置及分类应从以下几方面考虑:针对模块或系统某部分代码的调测;针对模块或系统某功能的调测;出于某种其它目的,如对性能、容量等的测试.
这样做便于软件功能的调测,并且便于模块的单元测试、系统联调等.
7-3:编写防错程序,然后在处理错误之后可用断言宣布发生错误.
示例:假如某模块收到通信链路上的消息,则应对消息的合法性进行检查,若消息类别不是通信协议中规定的,则应进行出错处理,之后可用断言报告,如下例.
#ifdef_EXAM_ASSERT_TEST_//若使用断言测试/*Notice:thisfunctiondoesnotcall'abort'toexitprogram*/voidassert_report(char*file_name,unsignedintline_no){printf("\n[EXAM]ErrorReport:%s,line%u\n",file_name,line_no);}#defineASSERT_REPORT(condition)if(condition)//若条件成立,则无动作NULL;else//否则报告assert_report(__FILE__,__LINE__)仅供内部使用40软件编程规范总则7可测性#else//若不使用断言测试#defineASSERT_REPORT(condition)NULL#endif/*endofASSERT*/intmsg_handle(unsignedcharmsg_name,unsignedchar*msg){switch(msg_name){caseMSG_ONE:.
.
.
//消息MSG_ONE处理returnMSG_HANDLE_SUCCESS;.
.
.
//其它合法消息处理default:.
.
.
//消息出错处理ASSERT_REPORT(FALSE);//"合法"消息不成立,报告returnMSG_HANDLE_ERROR;}}仅供内部使用41软件编程规范总则8程序效率8程序效率8-1:编程时要经常注意代码的效率.
说明:代码效率分为全局效率、局部效率、时间效率及空间效率.
全局效率是站在整个系统的角度上的系统效率;局部效率是站在模块或函数角度上的效率;时间效率是程序处理输入任务所需的时间长短;空间效率是程序所需内存空间,如机器代码空间大小、数据空间大小、栈空间大小等.
8-2:在保证软件系统的正确性、稳定性、可读性及可测性的前提下,提高代码效率.
说明:不能一味地追求代码效率,而对软件的正确性、稳定性、可读性及可测性造成影响.
8-3:局部效率应为全局效率服务,不能因为提高局部效率而对全局效率造成影响.
8-4:通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率.
说明:这种方式是解决软件空间效率的根本办法.
示例:如下记录学生学习成绩的结构不合理.
typedefunsignedcharBYTE;typedefunsignedshortWORD;typedefstructSTUDENT_SCORE_STRU{BYTEname[8];BYTEage;BYTEsex;BYTEclass;BYTEsubject;floatscore;}STUDENT_SCORE;因为每位学生都有多科学习成绩,故如上结构将占用较大空间.
应如下改进(分为两个结构),总的存贮空间将变小,操作也变得更方便.
typedefstructSTUDENT_STRU{BYTEname[8];仅供内部使用42软件编程规范总则8程序效率BYTEage;BYTEsex;BYTEclass;}STUDENT;typedefstructSTUDENT_SCORE_STRU{WORDstudent_index;BYTEsubject;floatscore;}STUDENT_SCORE;8-5:循环体内工作量最小化.
说明:应仔细考虑循环体内的语句是否可以放在循环体之外,使循环体内工作量最小,从而提高程序的时间效率.
示例:如下代码效率不高.
for(ind=0;indMAX_GT_LENGTH){returnGT_LENGTH_ERROR;//忘了释放gt_buf}.
.
.
//otherprogramcode}应改为如下.
intexample_fun(BYTEgt_len,BYTE*gt_code){BYTE*gt_buf;gt_buf=(BYTE*)malloc(MAX_GT_LENGTH);.
.
.
//programcode,includecheckgt_bufifornotNULL.
/*globaltitlelengtherror*/if(gt_len>MAX_GT_LENGTH){free(gt_buf);//退出之前释放gt_bufreturnGT_LENGTH_ERROR;}.
.
.
//otherprogramcode}9-7:防止内存操作越界.
说明:内存操作主要是指对数组、指针、内存地址等的操作.
内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心.
示例:假设某软件系统最多可由10个用户同时使用,用户号为1-10,那么如下程序存在问题.
#defineMAX_USR_NUM10unsignedcharusr_login_flg[MAX_USR_NUM]="";仅供内部使用48软件编程规范总则9质量保证voidset_usr_login_flg(unsignedcharusr_no){if(!
usr_login_flg[usr_no]){usr_login_flg[usr_no]=TRUE;}}当usr_no为10时,将使用usr_login_flg越界.
可采用如下方式解决.
voidset_usr_login_flg(unsignedcharusr_no){if(!
usr_login_flg[usr_no-1]){usr_login_flg[usr_no-1]=TRUE;}}9-8:认真处理程序所能遇到的各种出错情况.
9-9:系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用.
9-10:系统运行之初,要对加载到系统中的数据进行一致性检查.
说明:使用不一致的数据,容易使系统进入混乱状态和不可知状态.
9-11:严禁随意更改其它模块或系统的有关设置和配置.
说明:编程时,不能随心所欲地更改不属于自己模块的有关设置如常量、数组的大小等.
9-12:不能随意改变与其它模块的接口.
9-13:充分了解系统的接口之后,再使用系统提供的功能.
示例:在B型机的各模块与操作系统的接口函数中,有一个要由各模块负责编写的初始化过程,此过程在软件系统加载完成后,由操作系统发送的初始化消息来调度.
因此就涉及到初始化消息的类型与消息发送的顺序问题,特别是消息顺序,若没搞清楚就开始编程,很容易引起严重后果.
以下示例引自B型曾出现过的实际代码,其中使用了FID_FETCH_DATA与FID_INITIAL初始化消息类型,注意B型机的系统是在仅供内部使用49软件编程规范总则9质量保证FID_FETCH_DATA之前发送FID_INITIAL的.
MIDalarm_module_list[MAX_ALARM_MID];intFARSYS_ALARM_proc(FIDfunction_id,inthandle){_UIi,j;switch(function_id){.
.
.
//programcodecaseFID_INITAIL:for(i=0;i="误写成">"等造成的,由此引起的后果,很多情况下是很严重的,所以编程时,一定要在这些地方小心.
当编完程序后,应对这些操作符进行彻底检查.
9-15:要时刻注意易混淆的操作符.
当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误.
说明:形式相近的操作符最容易引起误用,如C/C++中的"="与"=="、"|"与"||"、"&"与"&&"等,若拼写错了,编译器不一定能够检查出来.
示例:如把"&"写成"&&",或反之.
ret_flg=(pmsg->ret_flg&RETURN_MASK);被写为:ret_flg=(pmsg->ret_flg&&RETURN_MASK);rpt_flg=(VALID_TASK_NO(taskno)&&DATA_NOT_ZERO(stat_data));被写为:rpt_flg=(VALID_TASK_NO(taskno)&DATA_NOT_ZERO(stat_data));9-16:有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支.
仅供内部使用51软件编程规范总则9质量保证9-17:Unix下,多线程的中的子线程退出必需采用主动退出方式,即子线程应return出口.
9-18:不要滥用goto语句.
说明:goto语句会破坏程序的结构性,所以除非确实需要,最好不使用goto语句.
9-1:不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性.
9-2:除非为了满足特殊需求,避免使用嵌入式汇编.
说明:程序中嵌入式汇编,一般都对可移植性有较大的影响.
9-3:精心地构造、划分子模块,并按"接口"部分及"内核"部分合理地组织子模块,以提高"内核"部分的可移植性和可重用性.
说明:对不同产品中的某个功能相同的模块,若能做到其内核部分完全或基本一致,那么无论对产品的测试、维护,还是对以后产品的升级都会有很大帮助.
9-4:精心构造算法,并对其性能、效率进行测试.
9-5:对较关键的算法最好使用其它算法来确认.
9-6:时刻注意表达式是否会上溢、下溢.
示例:如下程序将造成变量下溢.
unsignedcharsize;while(size-->=0)//将出现下溢{.
.
.
//programcode}当size等于0时,再减1不会小于0,而是0xFF,故程序是一个死循环.
应如下修改.
signedcharsize;//从unsignedchar改为signedcharwhile(size-->=0){.
.
.
//programcode}9-7:使用变量时要注意其边界值的情况.
仅供内部使用52软件编程规范总则9质量保证示例:如C语言中字符型变量,有效值范围为-128到127.
故以下表达式的计算存在一定风险.
charchr=127;intsum=200;chr+=1;//127为chr的边界值,再加1将使chr上溢到-128,而不是128.
sum+=chr;//故sum的结果不是328,而是72.
若chr与sum为同一种类型,或表达式按如下方式书写,可能会好些.
sum=sum+chr+1;9-8:留心程序机器码大小(如指令空间大小、数据空间大小、堆栈空间大小等)是否超出系统有关限制.
9-9:为用户提供良好的接口界面,使用户能较充分地了解系统内部运行状态及有关系统出错情况.
9-10:系统应具有一定的容错能力,对一些错误事件(如用户误操作等)能进行自动补救.
9-11:对一些具有危险性的操作代码(如写硬盘、删数据等)要仔细考虑,防止对数据、硬件等的安全构成危害,以提高系统的安全性.
9-12:使用第三方提供的软件开发工具包或控件时,要注意以下几点:(1)充分了解应用接口、使用环境及使用时注意事项.
(2)不能过分相信其正确性.
(3)除非必要,不要使用不熟悉的第三方工具包与控件.
说明:使用工具包与控件,可加快程序开发速度,节省时间,但使用之前一定对它有较充分的了解,同时第三方工具包与控件也有可能存在问题.
9-13:资源文件(多语言版本支持),如果资源是对语言敏感的,应让该资源与源代码文件脱离,具体方法有下面几种:使用单独的资源文件、DLL文件或其它单独的描述文件(如数据库格式)仅供内部使用53软件编程规范总则10代码编辑、编译、审查10代码编辑、编译、审查10-1:打开编译器的所有告警开关对程序进行编译.
10-2:在产品软件(项目组)中,要统一编译开关选项.
10-3:通过代码走读及审查方式对代码进行检查.
说明:代码走读主要是对程序的编程风格如注释、命名等以及编程时易出错的内容进行检查,可由开发人员自己或开发人员交叉的方式进行;代码审查主要是对程序实现的功能及程序的稳定性、安全性、可靠性等进行检查及评审,可通过自审、交叉审核或指定部门抽查等方式进行.
10-4:测试部测试产品之前,应对代码进行抽查及评审.
10-1:编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失.
10-2:同产品软件(项目组)内,最好使用相同的编辑器,并使用相同的设置选项.
说明:同一项目组最好采用相同的智能语言编辑器,如MuitiEditor,VisualEditor(我使用UltraEditor,ilan2003)等,并设计、使用一套缩进宏及注释宏等,将缩进等问题交由编辑器处理.
10-3:要小心地使用编辑器提供的块拷贝功能编程.
说明:当某段代码与另一段代码的处理功能相似时,许多开发人员都用编辑器提供的块拷贝功能来完成这段代码的编写.
由于程序功能相近,故所使用的变量、采用的表达式等在功能及命名上可能都很相近,所以使用块拷贝时要注意,除了修改相应的程序外,一定要把使用的每个变量仔细查看一遍,以改成正确的.
不应指望编译器能查出所有这种错误,比如当使用的是全局变量时,就有可能使某种错误隐藏下来.
10-4:合理地设计软件系统目录,方便开发人员使用.
说明:方便、合理的软件系统目录,可提高工作效率.
目录构造的原则是方便有关源程序的存储、查询、编译、链接等工作,同时目录中还应具有工作目录----所有的编译、链接等工作应在此目录中进行,工具目录----有关文件编辑器、文件查找等工具可存放在此目录中.
仅供内部使用54软件编程规范总则10代码编辑、编译、审查10-5:某些语句经编译后产生告警,但如果你认为它是正确的,那么应通过某种手段去掉告警信息.
说明:在BorlandC/C++中,可用"#pragmawarn"来关掉或打开某些告警.
示例:#pragmawarn-rvl//关闭告警intexamples_fun(void){//程序,但无return语句.
}#pragmawarn+rvl//打开告警编译函数examples_fun时本应产生"函数应有返回值"告警,但由于关掉了此告警信息显示,所以编译时将不会产生此告警提示.
10-6:使用代码检查工具(如C语言用PC-Lint)对源程序检查.
10-7:使用软件工具(如LogiSCOPE)进行代码审查.
仅供内部使用55软件编程规范总则11代码测试、维护11代码测试、维护11-1:单元测试要求至少达到语句覆盖.
11-2:单元测试开始要跟踪每一条语句,并观察数据流及变量的变化.
11-3:清理、整理或优化后的代码要经过审查及测试.
11-4:代码版本升级要经过严格测试.
11-5:使用工具软件对代码版本进行维护.
11-6:正式版本上软件的任何修改都应有详细的文档记录.
11-1:发现错误立即修改,并且要记录下来.
11-2:关键的代码在汇编级跟踪.
11-3:仔细设计并分析测试用例,使测试用例覆盖尽可能多的情况,以提高测试用例的效率.
11-4:尽可能模拟出程序的各种出错情况,对出错处理代码进行充分的测试.
11-5:仔细测试代码处理数据、变量的边界情况.
11-6:保留测试信息,以便分析、总结经验及进行更充分的测试.
11-7:不应通过"试"来解决问题,应寻找问题的根本原因.
(我是用试来查找问题的)11-8:对自动消失的错误进行分析,搞清楚错误是如何消失的.
(这个很有必要)11-9:修改错误不仅要治表,更要治本.
(说的很有道理)11-10:测试时应设法使很少发生的事件经常发生.
11-11:明确模块或函数处理哪些事件,并使它们经常发生.
11-12:坚持在编码阶段就对代码进行彻底的单元测试,不要等以后的测试工作来发现问题.
仅供内部使用56软件编程规范总则11代码测试、维护11-13:去除代码运行的随机性(如去掉无用的数据、代码及尽可能防止并注意函数中的"内部寄存器"等),让函数运行的结果可预测,并使出现的错误可再现.
仅供内部使用57软件编程规范总则11代码测试、维护12宏12-1:用宏定义表达式时,要使用完备的括号.
示例:如下定义的宏都存在一定的风险.
#defineRECTANGLE_AREA(a,b)a*b#defineRECTANGLE_AREA(a,b)(a*b)#defineRECTANGLE_AREA(a,b)(a)*(b)正确的定义应为:#defineRECTANGLE_AREA(a,b)((a)*(b))12-2:将宏所定义的多条表达式放在大括号中.
示例:下面的语句只有宏的第一条表达式被执行.
为了说明问题,for语句的书写稍不符规范.
#defineINTI_RECT_VALUE(a,b)\a=0;\b=0;for(index=0;indexa,rect.
b);正确的用法应为:#defineINTI_RECT_VALUE(a,b)\{\a=0;\b=0;\}for(index=0;indexa,rect[index].
b);}12-3:使用宏时,不允许参数发生变化.
示例:如下用法可能导致错误.
#defineSQUARE(a)((a)*(a))inta=5;intb;b=SQUARE(a+结果:a=7,即执行了两次增1.
正确的用法是:b=SQUARE(a);a++;//结果:a=6,即只执行了一次增1.
_仅供内部使用59

knownhost西雅图/亚特兰大/阿姆斯特丹$5/月,2个IP1G内存/1核/20gSSD/1T流量

美国知名管理型主机公司,2006年运作至今,虚拟主机、VPS、云服务器、独立服务器等业务全部采用“managed”,也就是人工参与度高,很多事情都可以人工帮你处理,不过一直以来价格也贵。也不知道knownhost什么时候开始运作无管理型业务的,估计是为了扩展市场吧,反正是出来较长时间了。闲来无事,那就给大家介绍下“unmanaged VPS”,也就是无管理型VPS,低至5美元/月,基于KVM虚拟,...

BuyVM老牌商家新增迈阿密机房 不限流量 月付2美元

我们很多老用户对于BuyVM商家还是相当熟悉的,也有翻看BuyVM相关的文章可以追溯到2014年的时候有介绍过,不过那时候介绍这个商家并不是很多,主要是因为这个商家很是刁钻。比如我们注册账户的信息是否完整,以及我们使用是否规范,甚至有其他各种问题导致我们是不能购买他们家机器的。以前你嚣张是很多人没有办法购买到其他商家的机器,那时候其他商家的机器不多。而如今,我们可选的商家比较多,你再也嚣张不起来。...

华纳云-618大促3折起,18元/月买CN2 GIA 2M 香港云,物理机高防同享,10M带宽独享三网直连,无限流量!

官方网站:点击访问华纳云活动官网活动方案:一、香港云服务器此次推出八种配置的香港云服务器,满足不同行业不同业务规模的客户需求,同时每种配置的云服务都有不同的带宽选择,灵活性更高,可用性更强,性价比更优质。配置带宽月付6折季付5.5折半年付5折年付4.5折2年付4折3年付3折购买1H1G2M/99180324576648直达购买5M/17331556710081134直达购买2H2G2M892444...

无法定位程序输入点于动态链接库为你推荐
赵雨润情人节“我们约会吧”电影DVD_我们约会吧高清DVD下载_qvod快播??免费开通黄钻能免费开通黄钻吗??百度抢票浏览器手机百度浏览器抢票版根本就没预约抢票。噱头而已!flash导航条flash导航条swf格式的要怎么编辑依赖注入Spring 的依赖注入是什么意思?唱吧电脑版官方下载电脑怎么安装唱吧,要能用的,请教教程,谢谢童之磊湖北中文在线数字出版有限公司怎么样?开机滚动条电脑开机有滚动条的画面lockdownd[求教]在淘宝买了张激活卡,请问怎么取消激活发邮件怎么发怎么发邮箱
电信服务器租用 locvps themeforest idc评测网 国外bt ev证书 国外php空间 中国电信测速网 如何注册阿里云邮箱 卡巴斯基免费试用版 web服务器搭建 全能空间 服务器论坛 xuni 带宽测试 上海联通 windowsserver2012r2 magento主机 hosting windowsserver2012 更多