Your SlideShare is downloading. ×
cppcheck源码分析
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

cppcheck源码分析

985
views

Published on

之前的两个PPT合并成一个,讲解cppcheck的源码

之前的两个PPT合并成一个,讲解cppcheck的源码


0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
985
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Cppcheck 架构分析 自动变量检查: Cppcheck 概述 返回自动变量(局部变量)指针 越界检查: 静态代码分析工具 数组越界 类检查: 构造函数,初始化检查点 内存泄露检查: 空指针检查: 废弃函数检查 其他:
  • 2. Cppcheck 架构分析总体
  • 3. Cppcheck 系统C++实现类
  • 4. 参数分析 外部输入 class Settings { 内部抽象 class Settings … std::string _append; std::string userDefines; std::list<std::string> _includePaths; std::list<Rule> rules; … } 字符交互模式 CmdLineParser parser(&_settings);
  • 5. Cppcheck总过程
  • 6. 预处理预处理阶段主要处理: 去多余空格 预处理处理由Preprocessor类 删除汇编代码 处理#Include及嵌套 实现 统一预处理语句(例:#if define=> #ifdef) 提取预处理配置设置(configuration) 执行Class Preprocessor::preprocess() 替换宏定义
  • 7. Tokenize 符号:+-*/;…等 变量名 函数名 解析代码成符号 由 class Tokenizer实现 实现接口 class Tokenizer::tokenize()
  • 8. Simplify目的: 简化复杂代码 统一化由 class Tokenizer实现实现接口 class Tokenizer::simplifyTokenList() Simplify规则 对变量 对条件循环语句if 、for、while (详细规则见word)
  • 9. Cppcheck 核心类class cppcheck Cppcheck程序的主干类 核心函数check() 处理入口,在此函数对输入代码进行初步分析处理,最后将代码传 递给 CheckFile(). 核心函数CheckFile() 函数功能是分析一个代码文件, CheckFile()会将代码流做 进一步的分析,做tokenize,simplify ,处理后分析代码,报告 错误
  • 10. Class cppcheck::check()函数 &class cppcheck:: CheckFile()函数的实现
  • 11. Cppcheck 检查实现类check
  • 12. 检查类的组织方式: static std::list<Check *> _instances;// Register this check class (by creating astatic instance of it)namespace std::list<Check *> &instances() static{ { 链表在哪? static std::list<Check *> _instances; CheckOther instance;} check类instances()函数中静态变量 return _instances; InlineCheck::Check(const std::string &aname) } : _name(aname), _tokenizer(0), _settings(0), _errorLogger(0) :{ 怎样加入检查类链表? instances().push_back(this); instances().sort(std::less<Check *>()); } 父类的构造函数执行时加入检查链表
  • 13. Class check protected: const std::string _name; const Tokenizer * const _tokenizer; const Settings * const _settings; ErrorLogger * const _errorLogger; Cppcheck核心类check virtual void runChecks(****){ } check子类都会实现 //不是所有 virtual void runSimplifiedChecks(***) = 0; //所有check子类都会实 现 void reportError() //报 告误差,所有check子类都会用到 virtual void getErrorMessages(****) = 0; //所有check子类都会实现, 最终都会调用reportError()Void runChecks() 主要是检查经过tokenize,但未经过simplify的代码流Void runSimplifiedChecks() 主要是检查经过tokenize,但未经过simplify的代码流
  • 14. 用户扩展接口 CheckOther : public Check Cppcheck 用户扩展类 …… CheckOther virtual void runChecks(****){ } virtual void runSimplifiedChecks(***) = 0; //实现 //实现 添加检查函数方法:
  • 15. Thank you
  • 16. 检查类cppcheck共有15个检查类实现了其检查功能
  • 17. 自动变量检查自动变量问题 自动变量也就是局部变量,存储空间在栈stack中,函数结束时空间被释放,如果此时变量地址被外部空间的函数使用,将会引起错误。自动变量暴露到外部窗口从参数(指向地址变量指针即指向指针的指针)return全局指针变量…其他 ….
  • 18. 错误举例:由参数传递局部变量地址 由程序返回int f(char ** fp) char* f(int i){ { Char c=’a’; char c=‘a’; *fp=&c; return 0; return &c;自动变量检查} }(error) Assigning address of (error) Return of the addresslocal auto-variable to a of an auto-variablefunction parameter.
  • 19. 自动变量检查实现类 class Ch eck Au toVariables
  • 20. Class CheckAutoVariablesautoVariables(); 检查自动变量returnPointerToLocalArray(); 检查是否返回了指向局部数组的指针returnReference() 检查是否返货了指向局部变量的引用returncstr() 检查是否返回局部字符串
  • 21. CheckAutoVariables.autoVariables()实现:关键变量:std::set<std::string> fp_list; 函数参数中指向指针的指针参数集合 std::set<unsigned int> vd_list; 自动变量集合 std::set<unsigned int> vda_list; 自动变量数组集合std::set<unsigned int> unknown_type;bool begin_function = false; 进入函数的标志bool begin_function_decl = false 进入函数参数声明部分标志函数
  • 22. CheckAutoVariables.autoVariables()错误捕获特征自动变量地址被赋给函数参数“[;{}] %var% = & %var%" %var%是fp_list . %var% in vd_list"[;{}] * %var% = & %var%" %var%是fp_list . %var% in vd_list"[;{}] %var% [ %any% ] = & %var%“ %var%是fp_list . %var% in vd_list自动变量地址返回 "return & %var% ;" %var% in vd_list无效空间释放"free ( %var% ) ;" isAutoVarArray %var% in vda_list
  • 23. .returnPointerToLocalArray()提取数组特征 "[;{}] %type% %var% [“ 将所有数组变量加入到 std::set<unsigned int>arrayVar错误特征 “return %var%” 且 %var% 在集合arrayVar中
  • 24. std::string & f(){ std::string str_local;返回引用函数的问题 return str_local;} 当f()运行结束时 str_local其实已经被释放了。 *好消息是 gcc就能查出此类问题
  • 25. .returnReference()描述:检查返回自动变量引用的函数(error) Returning reference to auto variable关键数据std::set<unsigned int> localvar;存储所有发现的自动变量寻找目标函数——返回引用的函数函数特征 "%type% & %var% (“ 或 "> & %var% ("
  • 26. .returnReference()提取数组特征“[;{}] %type% %var% [” 或 “%type% < %any% > %var%”;将所有自动变量 加入到 localvar错误特征 “return %var% ; ” 且 %var% 在集合calvar中
  • 27. .returncstr()描述:检查返回字符串自动地址的函数 (error) Returning pointer to auto variable关键数据 std::set<unsigned int> localvar; 存储所有发现的自动变量寻找目标函数——返回字符串的函数 特征 "const char *" 或 "> & %var% ("
  • 28. .returncstr()提取变量特征 "%type% %var% [;=]" localvar.insert(tok2->next()->varId()); 将所有自动变量 加入到 localvar错误特征"return %var% . c_str ( ) ;“且 %var% 在集合localvar中
  • 29. 存在问题没有处理指针传递识别不精确错误检查不精确
  • 30. 缓冲区溢出检查缓冲区溢出问题 缓冲区也就是一块内存空间,它可以是在栈中的局部变量(例如,静态数组),也可以是堆中的内存区域,程序中动态产生(例如,malloc,C++支持的动态数组)变量也就是局部变量。 所谓溢出也就是访问的地址空间超出了缓冲区内存区域,常见有两种方式导致溢出,一是显示的index越界,如数组越界,另外就是一些内存操作函数使用不当引发,如memcpy,memset…等内存操作函数
  • 31. 错误举例:由index越界 内存操作程序使用不当void f() void f(){ { char arrary[10]; char* buffer=new char c; char[10]; c= arrary[11]; memset(buffer,0,11);缓冲区溢出检查} }
  • 32. 缓冲区溢出检查实现类class Ch eckBu fferO verr un
  • 33. 缺陷不支持指针传递识别缓冲区精确度不高 动态数组,malloc固定空间等缓冲区不能识别 字符串常量 char* p=“hello” (注:这段空间不是缓冲区,不可写哦)内存操作函数检查的覆盖面不光,及一些双内存空间操作检查的不好如memcpy(void *destin, void *source, unsigned n);
  • 34. 类检查面向对象编程问题 c++的面向对象编程存在一些安全隐患,一 些经 典 的c++编程 书 籍都 有 提到 ,cppcheck实 现了《effective c++》中提到的一些安全隐患检查 如:多态基类需要实现vitual的析构函数 不在构造和析构函数中使用vitual函数 operator = 必须返回*this operator = 需处理自我赋值的情况 ……这些特性要加 –s 才启动
  • 35. 类检查实现类class Ch eck Class
  • 36. 类检查主要实现函数 checkClass.constructors(); checkClass.operatorEq(); checkClass.privateFunctions(); checkClass.thisSubtraction(); checkClass.checkConst(); checkClass.virtualDestructor(); checkClass.operatorEqToSelf();checkClass.operatorEqRetRefThis();
  • 37. 其他检查
  • 38. 检查扩充Cppch eck预留接口 class checkother
  • 39. 内存泄露检查内存泄露问题 内存泄露指的是在程序运行时,动态的申请了内存(堆),但是使用过后没有释放,导致一些内存永远得不到收回。 这是cppcheck最有价值的检查功能,也是实现代码最长的一块检查
  • 40. 内存泄露检查实现类class CheckMemor yLeakStructMemberclass CheckMemor yLeakInF unctionclass CheckMemor yLeakInClassclass CheckMemor yLeakNoVar
  • 41. CheckMemoryLeakStructMember检查内容: 在一个函数内、检查结构成员结构体被释放(返回)时,其成员不释放空间返回错误(error) Memory leak: STRUCT.MEMBER中间点表示成员
  • 42. Struct base{ char *p;}Void f()典型错误类型{ struct base *q; q=malloc(sizeof(struct base )) q->p=malloc(12); free(q);}
  • 43. Class CheckMemoryLeakStructMember void runSimplifiedChecks(…)实现接口(runSimplifiedChecks){ CheckMemoryLeakStructMember checkMemoryLeak( …); checkMemoryLeak.check();}核心函数 check() 辅助函数 getAllocType() getDeallocat ionType()
  • 44. Class CheckMemoryLeakInClass检查Ø1 成员变量在构造函数中赋空间,析构函数中没有被释放Ø2 成员变量在函数(所有函数,不单单是一个函数中)中分配空间,与释放空间函数不成匹配(malloc – free , new -delete)出现算法描述: 两个变量:Alloc Dealloc 一但对成员变量被分配空间,Alloc被置值,如果发现对变量释放空间函数,Dealloc置值,并立即对比,是否是同一类内存申请释放函数,如果不是,则立即报dismatch错,遍历完所有类的函数
  • 45. class base{private: int i; char *p; char *q;public : int j; base(); ~base();典型错误类型 void memalloc(); void memdealloc();}base::base(){ p= malloc(12);}void base::memalloc(){ q = malloc(12); free(p);}
  • 46. 错误输出否存在有Alloc无Dealloc的情况,有则报错memleak,(有函数中有申请,必须有函数释放,不一定在同一函数中申请释放)(error) Memory leak: CLASSNAME ::MEMBER发现不匹配(error) Mismatching allocation and deallocation CLASSNAME ::MEMBER检查构造函数,析构函数中是否成对(申请,释放)(如果构造中有内存申请,析构中必须有释放,)(error) Memory leak: CLASSNAME ::MEMBER
  • 47. Class CheckMemoryLeakInClass void runSimplifiedChecks(…)实现接口(runSimplifiedChecks){ … checkMemoryLeak.check();}核心函数 check() , variable() 辅助函数getAllocType() getDeallocationType()
  • 48. Void f(){典型错误类型 g(malloc(SIZE));}
  • 49. Class CheckMemoryLeakNoVar检查函数的参数部分有无内存泄露报错信息:(error) Allocation with FUNCNAME, FUNCNAME doesnt release it.
  • 50. Class CheckMemoryLeakNoVar void runSimplifiedChecks(…)实现接口(runSimplifiedChecks){ CheckMemoryLeakNoVar checkMemoryLeak( …); checkMemoryLeak.check();}核心函数 check() 辅助函数 getAllocType() getDeallocat ionType()
  • 51. Class CheckMemoryLeakInFunction检查以函数为单位的检查,参数,局部变量指针的检查 错误报告
  • 52. Void f(char *p,int i){ char *q;典型错误 p=malloc(10); q=malloc(10); return ;}
  • 53. Class CheckMemoryLeakInFunction实现接口(runSimplifiedChecks)void runSimplifiedChecks(…){ CheckMemoryLeakInFunction checkMemoryLeak( …); checkMemoryLeak.checkReallocUsage(); checkMemoryLeak.check();}核心函数 check() parseFunctionScope() checkScope() getcode()findLeak()辅助函数 getAllocType() getDeallocationType()
  • 54. 内存泄露新增重写了新的函数检查类Class CheckMemoryLeakInFunction_new