Pascal Analyzer 4 代码分析使用简要说明

概述

不管在那个开发团队中每个人的编写风格往往是千差万别能力也有高低,如何让别人快速看懂自己的代码维护你的代码。尽量避免不必要的简单错误,为编写代码作一定的约束是必不可少的。
如果你说我一个人不需要规范,其实不然。个人的代码风格能看出你的实际能力。犹如写文章一样杂乱有章,别人看都不愿意看,再精彩的故事也没用。日后自己维护也会头大。

因此有一份简单的代码编写约束是非常有必要的,不仅能提高可读性而且能提高代码质量。

1.    创建分析工程

打开软件后,有显示向导界面(默认关闭的,可以通过File菜单下的Run Wizard打开)在工程选择界面上选要分析的工程(如下图所示)

(图1)

选择工程后下一步,选择Delphi版本,选择后,在分析设置界面,我们可以选(Main File And Used Units),不用包括DFM文件,路径和条件设置界面中,可以把所有的选项都不选(这些可以在后面调整),选项确认后,会提示保存,可以选择保存(也可以不保存),选择后,工具进入分析阶段(需等一会儿),分析完,生成分析报告(如下图所示)

(图2)

也可以在进入界面后,直接新建工程(File菜单下的New Project 或工具条新建),新建后点击分析中的运行。

分析的工程文件(. dpr)不需要编译通过的,可以根据分析需要创建只包括需要分析的单元,这里要注意最好有工程同名的配置文件(.dof)。

2.    工程选项设置

在打开已有工程或新建工程后,选择工程属性(或通过New Project方式打开)

在这里需要关注的主要有:

a)         工程版本(Target version),该选项按实际情况选择(暂不确认对分析有什么影响)

b)        包含文件必须存在(Include Files must Exist),该选项可以不选(特别是有某些目录被排除的情况下,选择会导致分析报错并中断)

c)         使用工程设置(Use Delphi Project options if found),如果进行全工程分析时,可以选择此选择,选择此选项后,分析工具会使用工程中的搜索路径,分析的单元会很多。

d)        Delphi环境路径(Append Delphi library path 和Browsing path)该选项建议不选。

e)         分析排除路径(Exclude search path),有设置时,分析工具将不分析排除路径下的单元,因工程经常会携带一下第3方的控件,这种情况下,把这些控件目录及子目录排除,会减少不必要的分析(注意排除路径可能不支持相对路径,最好使用绝对路径,或直接通过向导设置)。

3.    分析报告解读

该工具的分析报告内容比较多,根据一段时间的使用和分析,感觉以下分析项目意义较大:

Warnings(警告方面):

Ambiguous unit references(重要)

Interfaces passed as parameters without "const" directive(重要)

Constructors/destructors without calls to inherited(重要)

Function result not set(重要)

Interfaced identifiers that are used, but not outside of unit(一般)

Interfaced class identifiers that are public/published, but not used outside of unit(一般)

Dangerous Exit-statements(一般)

Empty finally-block(一般)

Possible bad object creation(一般)

Ambiguous references in with-blocks(一般)

Optimization(优化方面):

Missing "const" for unmodified string parameter(重要)

Local subprograms with references to outer local variables(一般)

Memory(内存方面):

Local objects with unprotected calls to Free(一般)

Unbalanced Create/Free(一般)

Code Reduction(代码精简方面):

Local identifiers that are set and referenced once(一般)

Local long strings that are initialized to empty string(一般)

Boolean assignment can be shortened(一般)

Convention Compliance(习惯约定方面)

Local identifiers that "shadow" outer scope identifiers(一般)

Inconsistent Case(大小写不一致方面)

Inconsistent case for same identifier(一般)

下面对这些关注方面进行简要说明,方便理解。

警告提示(Warnings)

重要关注方面

a)         不明确的引用关系(Ambiguous unit references)

该提示说明,使用的常量、函数、过程有重名现象,这些需要分析,尽量消除。

b)        接口类型参数未加const 声明(Interfaces passed as parameters without "const" directive)

function Save(ADB: IBaseDBIntf): Boolean; virtual;

接口作为参数传递,未加const 声明时,编译器在调用时 会加上 _AddRef 调用结束后会加上 _Release,这在频繁调用时会降低效率。

c)         解构/析构未继承调用(Constructors/destructors without calls to inherited)

如果类继承父类,解构时未继承调用可能会导致父类未初始化;析构时未继承调用可能会导致内存泄漏。类似的还包括(Destructors without override 未声明覆盖)。

d)        函数未设置返回值(Function result not set)

function TdlgInputHuanSuanLv.ActOkNotify: Boolean;
begin
  DoOk;
end;

该情况Delphi编译时,通常也有警告提示,函数未设置返回值可能会导致不可预料的结果。

一般关注方面

a)         对外定义(包括类、函数等声明)被使用了,但只在本单元内(Interfaced identifiers that are used, but not outside of unit)

简单示例如function BoolToInt

function BoolToInt(ABoolValue: Boolean): Integer;

implementation

{$R *.dfm}

function BoolToInt(ABoolValue: Boolean): Integer;
begin
  Result := Integer(ABoolValue);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowMessage(IntToStr(BoolToInt(False)));
end;

这个提示可以列出一些不必要公布的函数或类,对这些函数或类进行一些分析后,可能会有新的归类和设计。

b)        对外公布类的公共属性和方法,只在本单元使用了(Interfaced class identifiers that are public/published, but not used outside of unit)

这个提示可以用来帮助精简对外公用的属性和方法

c)         危险的退出(Dangerous Exit-statements)

在一个过程、函数中,如果开头有Exit 就会提示该信息,这通常有两种情况:一是该过程不使用了,建议删除该过程;另一种是调试时增加的代码,但忘记删除了,这个需要确认核实。

d)        空的强制执行模块(Empty finally-block)

有该提示的 Try … finally结构可以删除,提高代码效率。

e)         可能是错误类创建过程(Possible bad object creation)

procedure Proc;
var
  Bmp : TBitmap;
begin
  Bmp.Create; //错误
end;
procedure Proc2;
begin
  TNode.Create(Parent);//内存泄漏
end;

有这样提示的代码可能或导致错误或内存泄漏。

f)         危险的块声明引用(Ambiguous references in with-blocks)

procedure TForm1.Button1Click(Sender: TObject);
begin
  with Button1 do
  begin
    Caption := ‘test‘;
  end;
end;

这种提示通常发生在 块定义的类实例和过程所属的类有同名的属性或过程(如上图代码 Caption),这在复杂逻辑中往往会导致问题。

优化建议(Optimization)

重要关注方面

a)         未发生修改的字符串参数未声明为const (Missing "const" for unmodified string parameter)

function LoadSQL(ACondition: string; AOnlyStruct: Boolean = False): 

因字符串有引用计数,在明确知道不需要修改的字符串参数前,请加上 const,这样可以提高效率。类似的参数还有 record、array、Interface等。

一般关注方面

a)         子过程使用过程外的变量(Local subprograms with references to outer local variables)

procedure TSelectTextHelper.InitFields(AFields: TSerializableFields; AItem: TSerializeItem);
var
  i: Integer;
  aField: TSerializableField;
  procedure InnerAddField(AIdx: Integer);
  begin
    aField := TSerializableField(AFields.Append);
   aField.FieldName := aField.FieldItem.ClassFieldName;
    aField.DataType := TypeKindToFieldType(aField.FieldItem.DataType);
  end;
begin
  AFields.Clear;
  if AItem <> nil then
  begin
    i := AItem.ObjFieldsMap.IndexByName(AItem.KeyField);
    InnerAddField(i);
  end;
end;

如上面的代码所示,子过程使用外面的 aField,这种情况需要尽量避免(特别是影响效率的代码段),建议子过程尽量放在 变量声明前面。

内存建议(Memory)

一般关注方面

a)         过程内的对象未在保护结构内释放(Local objects with unprotected calls to Free)

var
  aList: TList;
begin
   aList := TList.Create;
   ;//省略逻辑过程
   aList.Free;

对象释放过程没有在保护结构时,如果释放前有异常抛出或提前退出时,会导致内存泄漏,建议释放过程尽量使用 try … finall结构。

b)        不对称的创建释放(Unbalanced Create/Free)

procedure LocalProc;
var
  Obj: TMyClass;
begin
  Obj := TmyClass.Create;
  Obj.DoSomething;
end;

不对称释放,往往会导致内存泄漏,但分析工具对一些加入列表的、全局对象等判断不够,导致很多误报。另外还有下面这种情况也不提倡使用,最好把返回对象作为参数传入,这样可能避免疏忽引起的泄漏

function TForm1.GetList: TStringList;
begin
   ;//省略逻辑
  Result := TStringList.Create;
end;
//建议改成
procedure TForm1.GetList(Alist: TstringList);
begin
   ;//省略逻辑
end;

代码精简建议(Code Reduction)

一般关注方面

a)         过程内本地变量只使用一次(Local identifiers that are set and referenced once)

var
   aData: TSearchResult_Data;
begin
  if FDataList <> nil then
  begin
    aData := TSearchResult_Data(FDataList.Items[AIndex]);
    if not aData.Valid then
      Value := cst_Invalid_Price;
  end;
end;

//可精简为
begin
  if FDataList <> nil then
  begin
    if not TSearchResult_Data(FDataList.Items[AIndex]).Valid then
      Value := cst_Invalid_Price;
  end;
end;

不在循环体内的只使用一次的变量往往可以精简,如上图,这种情况要具体情况具体分析,有很多时候,分析报告这方面的提示是不正确的。类似的还有Local identifiers that possibly are set and referenced once,这里不另外列举。

b)        过程内字符串变量初始化为空(Local long strings that are initialized to empty string)

var
  s: string;
begin
  s := ‘‘;
  ;//省略逻辑

如上例所示,s设置为空是没有必要的,编译器已经自动初始化了。

c)         布尔赋值可以更精简(Boolean assignment can be shortened)

       if CheckedCount > 0 then
          NewState := True
        else
          NewState := False;

//可以精简为
        NewState := CheckedCount > 0;

该类提示往往是代码使用了条件判断再赋值的方式,该类代码可以优化另外也可以关注(Unneeded boolean comparisons)。

习惯约定建议(Convention Compliance)

一般关注方面

a)         参数重名情况Local identifiers that "shadow" outer scope identifiers

procedure TfrmMessageDlg.showButton(flags, timeCount: Integer);

  function GetButtons(Flags: integer): TMsgDlgButtons;
  begin
     ;//省略逻辑
  end;

begin
  ;//省略逻辑
end;

该情况一般发生在过程下有子过程中,如上面的代码所示,建议不要重名现象,重名会导致易读性下降。

大小写不一致建议(Inconsistent Case)

一般关注方面

a)         相同定义大小写不一致Inconsistent case for same identifier

  procedure DoSaveEvent(ATotal, ACur: Integer);
  begin
    if Assigned(FSaveEvent) then
      FSaveEvent(aTotal, aCur);
  end;

如上面的代码所示,参数位大写,在使用时为小写,这个不符合编码规范,建议关注这方面的提示,使代码更规范。

4.    结束语

在团队合作中统一的代码规范是非常有必要的。提高代码质量、提高代码可读性等起到一定作用,上面只是列举了部分内容,分析报告中的General分支下还有很多好的建议,我们日常工作中都能应用到,另外该工具的帮助文档虽然简单,但各项建议的含义都有说明,大家不妨读一下。

http://www.cnblogs.com/gleam/archive/2013/05/08/3066679.html

时间: 2024-10-14 09:22:02

Pascal Analyzer 4 代码分析使用简要说明的相关文章

你不知道的常用 代码分析 规范

visual studio有个功能,代码分析,一般开发完毕后,除了处理常规的“错误列表”显示的“错误”和“警告”,我们更加应该注意的是,运行代码分析功能,规范我们的代码,因为不好的编码习惯,在没有人指出和没有团队氛围的开发中,很多时候都是一路不规范到底 visual studio菜单的“分析”->“对***运行代码分析”或者在解决方案的类库右击选择代码分析如果为了强迫自己养成良好的c#微软规范的习惯,我们可以右击类库属性,找到最后一行标签“代码分析”,并在对应右侧明细的“规则集”->"

Android4.0图库Gallery2代码分析(二) 数据管理和数据加载

Android4.0图库Gallery2代码分析(二) 数据管理和数据加载 2012-09-07 11:19 8152人阅读 评论(12) 收藏 举报 代码分析android相册优化工作 Android4.0图库Gallery2代码分析(二) 数据管理和数据加载 一 图库数据管理 Gallery2的数据管理 DataManager(职责:管理数据源)- MediaSource(职责:管理数据集) - MediaSet(职责:管理数据项).DataManager中初始化所有的数据源(LocalSo

恶意代码分析实战

恶意代码分析实战(最权威的恶意代码分析指南,理论实践分析并重,业内人手一册的宝典) [美]Michael Sikorski(迈克尔.斯科尔斯基), Andrew Honig(安德鲁.哈尼克)著   <恶意代码分析实战>是一本内容全面的恶意代码分析技术指南,其内容兼顾理论,重在实践,从不同方面为读者讲解恶意代码分析的实用技术方法. <恶意代码分析实战>分为21章,覆盖恶意代码行为.恶意代码静态分析方法.恶意代码动态分析方法.恶意代码对抗与反对抗方法等,并包含了 shellcode分析

免费的Lucene 原理与代码分析完整版下载

Lucene是一个基于Java的高效的全文检索库.那么什么是全文检索,为什么需要全文检索?目前人们生活中出现的数据总的来说分为两类:结构化数据和非结构化数据.很容易理解,结构化数据是有固定格式和结构的或者有限长度的数据,比如数据库,元数据等.非结构化数据则是不定长或者没有固定格式的数据,如图片,邮件,文档等.还有一种较少的分类为半结构化数据,如XML,HTML等,在一定程度上我们可以将其按照结构化数据来处理,也可以抽取纯文本按照非结构化数据来处理.非结构化数据又称为全文数据.,对其搜索主要有两种

基于OAuth2.0协议的QQ第三方授权登录iOS代码分析

简要说明: 授权登录已经成为注册方式里的主流,目前授权登录方式主要SSO跳转授权登录和OAuth2.0两种,前者好处无需用户再次输入密码就可以直接授权成功,但前提是必须用户手机端安装了该软件,比如QQ,后者的优势就是是否安装无关紧要,是一个HTML的页面呈现,麻烦就在于要输入用户名和密码,这就非常不爽了,但是有时候偏偏必须这么做,理由嘛,自行想想就好,接下来我们就看看如果利用OAuth2.0的方式来做QQ授权登录,如果想了解QQ的SSO授权登录,可以看我(博客主页)之前的博客:基于第三方QQ授权

HEVC码率控制算法研究与HM相应代码分析(三)——算法及代码分析

在前两篇文章中,首先介绍了HEVC标准和编码流程,然后介绍了在HEVC中采用的全新的R-λ模型,本文将基于前面的内容和相应代码对码率控制算法进行详细的分析. 下面基于JCTVC-K0103提案详细介绍一下HEVC中基于R-λ模型的码率控制方法.同时基于HM-10对码率控制部分的代码做一个简要分析,相比于JM,HM中更多的使用了面向对象技术,结构更加清楚明了,码率控制相关代码的基本调用层次如下,纵向上即层层调用的关系,横向上是对几个比较重要的函数的内部调用情况列了出来. 跟以前的方法类似,码率控制

2017-2018-2 《网络对抗技术》 20155322 Exp4 恶意代码分析

[-= 博客目录 =-] 1-实践目标 1.1-实践介绍 1.2-实践内容 1.3-实践要求 2-实践过程 2.1-Mac下网络监控 2.2-Windows下网络监控 2.3-Mac下恶意软件分析 2.4-Windows下恶意软件分析 2.5-基础问题回答 3-资料 1-实践目标 1.1-恶意代码分析 一般是对恶意软件做处理,让它不被杀毒软件所检测.也是渗透测试中需要使用到的技术. 要做好免杀,就时清楚杀毒软件(恶意软件检测工具)是如何工作的.AV(Anti-virus)是很大一个产业.其中主要

java代码分析及分析工具

java代码分析及分析工具 一个项目从搭建开始,开发的初期往往思路比较清晰,代码也比较清晰.随着时间的推移,业务越来越复杂.代码也就面临着耦合,冗余,甚至杂乱,到最后谁都不敢碰. 作为一个互联网电子商务网站的业务支撑系统,业务复杂不言而喻.从09年开始一直沿用到现在,中间代码经过了多少人的手,留下了多少的坑,已经记不清楚了,谁也说不清了. 代码的维护成本越来越高.代码已经急需做调整和改善.最近项目组专门设立了一个小组,利用业余时间做代码分析的工作,目标对核心代码进行分析并进行设计重构. 代码分析

Java静态代码分析工具Infer

Java静态代码分析工具Infer 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.Infer介绍 Infer是Facebook最新开源的静态程序分析工具,用于在发布移动应用之前对代码进行分析,找出潜在的问题.目前Facebook使用此工具分析Facebook的App,包括Android.iOS.Facebook Messenger和Instagram等. Facebook称该工具帮助其每个月检查出应用潜在的数百个Bug,例如一些空指针访问.资源