TscanCode 静态代码分析实战:C/C++、C、Lua 三语言缺陷检测的编译、使用与规则原理剖析 静态分析代码质量开发工具质量保障【免费下载链接】TscanCodeA static code analyzer for C, C#, Lua项目地址https://gitcode.com/gh_mirrors/ts/TscanCode点击查看免费下载TscanCode 是腾讯开源的静态代码分析工具面向 C/C、C# 和 Lua 三类语言目标是帮助程序员在编码阶段尽早发现代码缺陷。本文基于项目根目录的 README.md 展开完整覆盖其功能定位、编译方式与一行命令上手流程并结合 trunk 源码进一步剖析命令参数的底层实现、README 中示例错误的检测原理以及cfg.xml规则配置体系帮助读者既能开箱即用也能读懂 TscanCode 的检测机制与可定制点。一、项目定位与核心特性TscanCode 的自我定位是一句直白的话A fast and accurate static analysis solution for C/C, C#, Lua codes即帮助开发者在缺陷刚出现时就把它找出来help programmers to find out code defects at the very beginning。README 中列出了四条核心特性特性说明多语言同时支持C/C、C#、Lua三种语言的代码分析快速且准确官方给出的性能指标为约 200K 行代码/分钟准确率约 90%易用不需要严格的编译环境单条命令即可完成检查可扩展支持用户自定义 check 规则从仓库的组织结构看README 描述的语言分布是清晰的C/C 分析引擎完整开源位于 trunk包含lib/核心分析库、cli/命令行入口、common/路径与文件枚举等公共模块、externals/tinyxml/XML 输出依赖C# 与 Lua 版本README 明确说明codes under trunk are only for TscanCode CPP version, C# and Lua version are in the internal review process即这两种语言的引擎源码未随仓库开放但release/目录下提供了各平台的可执行程序如 TscSharp、tsclua且 samples 下配有完整的三语言示例。版本演进方面README 记录了几个关键节点v2.15.022022-04-28修复 Lua 崩溃问题开放更多 checkerv2.15.012022-01-19支持 Lua 5.4并带来一批 bug 修复与新特性v2.14.242018-02-24GUI 发布 Rule Package 便于规则定制GUI 支持标记误报。更完整的变更历史可查阅 CHANGELOG.md例如其中还记录了 2.11.27 版本新增的lua_VarSpellWrongErrorLua 变量拼写错误检查、CS_UnityMessgeSpellWrongUnity 消息函数拼写检查如把OnDestroy误拼成OnDestory等细节。二、编译构建一条make命令的完整工程拆解2.1 编译器要求README 给出的编译前提是任意支持 C11 的编译器均可编译部分支持 C11 的编译器也可能工作最低参考线是 Visual Studio 2015 所具备的 C11 特性若编译器不支持nullptr可以通过 lib/cxx11emu.h 头文件做模拟兼容平台选项Windows 用 Visual Studio 2015Linux 用 g 4.6macOS 用 clang。2.2 Visual Studio 构建Windows 下使用解决方案文件 trunk/tscancode.sln该文件默认配置为 Visual Studio 2015但可以方便地切换到新旧版本的平台工具集解决方案同时包含 x86 与 x64 两个平台目标选择Release配置即可产出发布版本。2.3 Linux/macOSmake构建细节在 trunk 目录下执行make这条零依赖命令背后的构建规则定义在 trunk/Makefile 中值得逐条看一下ifndef CXX CXXg endif ifndef CXXFLAGS CXXFLAGS-stdc0x -O2 -include lib/cxx11emu.h -DNDEBUG -Wall -Wno-sign-compare -Wno-unknown-pragmas -Wno-reorder endif # Force including libpthread LIBS-lpthread几个关键点-include lib/cxx11emu.hMakefile 默认把cxx11emu.h强制包含进每个编译单元这正是 README 中不支持 nullptr 时用它模拟的落地方式-lpthread强制链接分析引擎内置多线程执行器对应 cli/tscthreadexecutor.cpp因此 Linux 构建必须链接 pthread产物构成最终目标tscancode由四组对象文件链接而成——LIBOBJtrunk/lib 下约 50 个分析核心源文件如check*.o、tokenize.o、valueflow.o等、CLIOBJtrunk/cli 下的main.o、cmdlineparser.o、tscexecutor.o、tscthreadexecutor.o、COMMONOBJtrunk/common 下的路径与文件枚举模块以及外置的externals/tinyxml/tinyxml2.o支持通过CXX、CXXFLAGS环境变量覆盖默认编译器与编译选项。三、一分钟上手从空指针示例到 XML 报告README 用了一个经典空指针缺陷作为Usage at a glance示例。下面这段代码的问题在于对p做判空只说明p可能为空因此在if作用域之外解引用*p是不安全的// func.cpp void func(int* p) { if(p NULL) { printf(p is null!); } printf(p is %d, *p); }执行检查./tscancode --xml func.cpp 2result.xml注意--xml会把结果以 XML 格式写到错误流stderr因此用2result.xml重定向。报告内容如下?xml version1.0 encodingUTF-8? results error filefunc.cpp line7 idnullpointer subiddereferenceAfterCheck severityerror msgComparing [p] to null at line 3 implies [p] might be null. Dereferencing null pointer [p]. / /results报告字段含义file/line定位到第 7 行的解引用id为检查类别nullpointersubid为具体缺陷子类dereferenceAfterCheck先判空、后在判空作用域外解引用severity为严重级别msg是可读的诊断说明。3.1 这个错误是谁报出来的——源码级溯源dereferenceAfterCheck这个 subid 的报错实现位于 trunk/lib/checktscnullpointer2.cpp 的nullPointerError函数中。该函数根据表达式取值状态CExprValue分派到不同 subidelse if (ev.IsCondCheckNull()) { ss Comparing [ sExprLoc.Expr.ExprStr ] to null at line ... // 若表达式含 ( 归类为 funcDereferenceAfterCheck // 若表达式含 [ 归类为 arrayDereferenceAfterCheck // 否则普通指针/变量走下面分支 reportError(sExprLoc.Begin, Severity::error, ErrorType::NullPointer, dereferenceAfterCheck, ss.str().c_str(), ...); }也就是说README 示例中那句Comparing [p] to null at line 3 implies [p] might be null...的完整错误文本正是由这段拼接逻辑生成。同一函数还区分了其他变体invalidDereferenceIterator迭代器失效解引用、funcRetNull函数返回值判空缺陷、explicitNullDereference显式空指针解引用等。3.2 subid 规则表cfg.xml 中的规则开关与中文释义每个 subid 的启用状态value、严重级别severity、规则中文名与说明集中在 trunk/cfg/cfg.xml 的nullpointer节点中例如id namenullpointer value1 subid namedereferenceAfterCheck value1 severitySerious rule_name先判空后解引用 desc指针先判空然后在判空作用域外解引用……/ subid namefuncRetNull value0 severityWarning rule_name函数返回值未判空解引用 desc……/ subid namedereferenceIfNull value1 severityCritical rule_name指针为空解应用 descif条件判断指针等于NULL成立时对指针解引用通常是判空条件写反了导致的/ ... /idvalue1表示该规则默认启用value0表示默认关闭severity分Critical/Serious/Warning/Information四级。同文件中还以同样的粒度管理bufoverrun缓冲区越界、memleak内存泄漏等类别每类都带有中文rule_name与desc。发布包 release/linux/TscanCodeV2.14.2395.linux/cfg 下除cfg.xml外还附带std.cfg、windows.cfg、posix.cfg、qt.cfg、gtk.cfg、sdl.cfg、avr.cfg、gnu.cfg、microsoft_sal.cfg等平台/标准库配置供不同代码库按需加载C# 侧对应 TscSharp 的 cfg_cs.ini 与 rule.xmlLua 侧对应 TscLua/cfg 下的lua_cfg.xml、lua_std.cfg等。四、命令行参数全景从帮助文本到解析实现./tscancode --help或-h输出的帮助文本定义在 trunk/cli/cmdlineparser.cpp 的PrintHelp()中。README 只演示了--xml一个参数下面把ParseFromArgs()cmdlineparser.cpp实际支持的参数完整整理如下均以当前仓库源码为准4.1 基础与输出控制参数作用-h, --help打印帮助后退出-q, --quiet不打印进度报告--xml将结果以 XML 格式写入 stderrREADME 示例所用--xml-versionn指定 XML 版本仅支持 1 或 2同时隐含启用--xml-v, --verbose输出更详细的配置信息--errorlist打印所有可能的错误消息后退出隐含启用 XML--templatefmt自定义输出模板支持{file}、{line}、{severity}、{message}等占位符内置快捷值gcc{file}:{line}: {severity}: {message}、vs{file}({line}): ...、edit-rp, --relative-paths[base1;base2]输出相对路径可用;分隔指定多个基准路径--error-exitcoden检查发现错误时以指定整数码退出便于 CI 集成--report-progress报告检查进度--showtimefile\|summary\|top5显示耗时统计4.2 预处理与包含路径参数作用-DID/-DIDVAL定义预处理宏不带时自动补1。源码中有一处实用逻辑只要使用了-D且未加--force/--max-configs就会把--max-configs设为 1即只检查给定宏配置的那一种#ifdef分支避免配置爆炸-UID取消宏定义显式隐藏某些#ifdef分支-I dir/-Idir给出头文件搜索路径可多次指定先给出的路径优先--includes-filefile从文件逐行读取包含路径--includefile指定必须包含的文件--config-excludepath/--config-excludes-file配置排除路径4.3 抑制与过滤参数作用--suppressid按 id 抑制指定错误--suppressions-listfile从文件读取抑制规则一个参数只能带一个文件多文件需多次传参--inline-suppr启用源码内联抑制注释--exitcode-suppressionsfile指定不影响退出码的抑制规则4.4 性能、平台与语言控制参数作用-j jobs/-jn多线程检查上限 10000源码中有保护逻辑unusedFunction检查与-j不兼容会提示并禁用该检查-l n按系统负载控制并发-f, --force强制检查所有#ifdef配置_maxConfigs ~0U--max-configsn限制检查的最大#ifdef配置数指定后会重置--force--stdc89\|c99\|c11\|c03\|c11\|posix指定语言标准影响内置函数库的语义理解--platformwin32A\|win32W\|win64\|unix32\|unix64\|native指定目标平台影响平台相关的类型宽度分析-x c\|c/--language强制指定待检语言-i path忽略指定目录如生成代码目录--file-listfile从文件逐行读取待检文件列表文件名为-时读 stdin--enableid帮助文本列出了all/warning/style/performance/portability/information/unusedFunction/missingInclude等 id但源码解析处将其标注为for compatibility only直接跳过因为ParseFromArgs末尾默认执行addEnabled(all)——当前版本默认启用全部检查--libraryname加载库定义配合 cfg 目录下的平台/标准配置--lua filePath指定 Lua 项目路径启用 Lua 检查模式--check-config/--check-library检查包含配置 / 检查库定义文件的正确性--appendfile向待检代码尾部追加用户自定义代码--rulepattern/--rule-filefile自定义规则--rule-file读取含rule/tokenlist/pattern/message节点的 XML解析逻辑见 cmdlineparser.cpp对应 README 宣称的可自定义 check能力--no-analyze/--no-check关闭分析/检查阶段调试用--debug、--debug-normal、--debug-warnings、--debug-fp、--dump*系列各类调试输出开关-rf, --recordfuncinfo/--cfg-merge/-e2o记录函数信息 / 合并两个 cfg.xml / 内部开关用法示例摘自帮助文本# 递归检查当前目录进度打到屏幕错误写入文件 tscancode . 2 err.txt # 递归检查项目且不打印进度 tscancode --quiet ../myproject/ # 检查单个文件并启用全部检查 tscancode --enableall test.cpp # 检查 f.cpp 并从 inc1/、inc2/ 搜索头文件 tscancode -I inc1/ -I inc2/ f.cpp另外参数以-开头但无法识别时会报unrecognized command line option并退出命令行未给任何源文件/目录时报No C or C source files found。五、示例集与目录结构每个规则都能找到对应样本README 指向三个示例目录仓库中确实一一对应且样本文件名与 subid 同名可直接用于回归验证某条规则C/C 样本samples/cpp共 80 个样本如 dereferenceAfterCheck.cppREADME 同类场景if(obj ! NULL)保护之外的obj-dosth2()、arrayindexoutofbounds.cpp、memleak.cpp、unsignedlessthanzero.cpp、recursivefunc.cpp、stlsortcheck.cpp等覆盖空指针、越界、内存泄漏、逻辑缺陷、STL 误用等 cfg.xml 中的主要类别C# 样本samples/csharp如cs_arrayindexoutofbound.cs、cs_dereferenceifnull.cs、cs_unreleasedlock.cs、cs_inherit/update系列cs_inefficientupdate.cs、cs_foreachinupdate.cs等 Unity 相关检查Lua 样本samples/lua如lua_Uninitvar.lua、lua_undeclaredvar.lua、lua_UseVarIfNil.lua、lua_keywordspellwrongerror.lua对应 CHANGELOG 提到的拼写类检查。每个样本文件通常只含十几行最小缺陷代码适合作为规则行为的最小复现样例。六、发布包与平台适配release 目录按平台组织可直接下载使用预编译版本平台内容release/linuxTscanCodeV2.14.2395.linux/tscancode 可执行文件 cfg/ 全套规则配置、TscSharpV1.14.667.linux/C# 分析器 cfg_cs.ini rule.xml、TscLua/Lua 分析器 cfg附 READMErelease/mactscancode、TscSharp、tsclua.mac与全套 cfg含filter.ini、rule.xmlrelease/windows/luatsclua.exe与核心库tsclua-core.dll、cfg 配置发布包命名即版本信息如 V2.14.2395、V1.14.667而源码 trunk/lib/version.h 中当前版本宏为2.14.2397README 徽标则标注 2.15.02三者分别对应发布包、源码修订与对外发布的口径实际使用请以目标二进制自带的--version输出为准。七、适用边界与注意事项开源范围trunk/仅包含 C/C 版本的分析引擎源码C# 与 Lua 引擎源码按 README 说明仍在内部评审流程中未开放但两类语言的发布二进制、配置文件与 samples 均已随仓库提供性能与准确率200K 行/分钟与约 90% 的准确率是 README 给出的官方指标实际吞吐与误报率会随代码库复杂度、#ifdef配置数量和-D/--force用法而变化静态分析的固有限制TscanCode 不要求完整编译环境这正是其易用性的来源但也因此对跨文件语义的理解依赖cfg配置与内置库定义对未定义行为的判定部分依赖统计推断如 cfg.xml 中默认关闭的funcRetNullStatistic、OutOfBoundsStatistic等基于统计推断类规则若需了解各版本具体改动请查阅 CHANGELOG.md若需要扩展自定义规则可参考--rule/--rule-file的 XML 格式与 cfg.xml 中的rule_name/desc组织方式。赞分享静态分析代码质量开发工具质量保障【免费下载链接】TscanCodeA static code analyzer for C, C#, Lua项目地址https://gitcode.com/gh_mirrors/ts/TscanCode点击查看免费下载相关推荐Infer 静态分析器完全指南Java/C/C/Objective-C 跨文件深层缺陷检测的原理与工程实践Infer 静态分析器完全指南Java/C/C/Objective C 跨文件深层缺陷检测的原理与工程实践 导读本文以 Infer 官方文档 02 ab静态分析代码质量开发工具代码零缺陷C静态分析工具精选指南代码零缺陷C静态分析工具精选指南 你还在为调试C内存泄漏焦头烂额还在担心上线前遗漏安全漏洞本文将带你掌握静态代码分析Static Code An文档教程LittleD编译时配置详解如何定制嵌入式数据库功能以满足应用需求LittleD编译时配置详解如何定制嵌入式数据库功能以满足应用需求 LittleD是一款专为嵌入式设备和传感器节点设计的关系型数据库通过灵活的编译时配置开数据库嵌入式上一篇CodePilot 上下文用量可视化实战Context Usage Breakdown 数据契约与点阵式组成条实现下一篇Marvin Tasks 结构化 AI 任务框架类型安全、可靠执行与任务编排实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考