前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >温故知新:静态分析

温故知新:静态分析

作者头像
半吊子全栈工匠
发布2021-11-16 10:17:55
2560
发布2021-11-16 10:17:55
举报
文章被收录于专栏:喔家ArchiSelf喔家ArchiSelf

代码在计算机上运行,但用途并不限于此,同样是用来阅读和理解的。不易理解的代码不能轻易地维护或改进,代码库的复杂性与其缺陷率之间存在着相关性。理解大型的代码库是困难的,因此需要各种工具和技术来协助。

静态代码分析(简称静态分析)工具,是由程序或算法组成的,从一个程序的源代码中提取事实,而不需要执行有问题的程序,通常作为日常软件开发过程中的一个特定阶段。通过使用工具进行静态分析,有机会使用分析中产生的事实来进一步理解、评估和修改相关的代码。可以从源码中提取的数据目标可以分为很多类,例如,安全漏洞的分析会提取程序中的函数和库信息,而代码布局的分析则会关注语法结构的位置。常见的目标还包括无用代码检测,是否使用了不安全的 api,识别和监视可能被恶意数据污染的值, 竞争条件检测,确保对数组或内存位置的访问在预期的范围之内,等等。

静态分析和动态分析常常同时使用。动态分析从程序的运行时提取事实数据,检查并验证程序的正确性。静态分析的一个好处是,通常可以操作程序中所有可能的执行分支,而动态分析只能访问当前正在执行的代码路径。然而,动态分析有关于数据在运行程序内存中的布局和位置的具体信息,而静态分析则必须猜测给定的语言、编译器、操作系统和计算机体系结构将如何表示特定的数据。另外,二者有一定程度的重叠,例如动态分析和静态分析都可以检测 c 语言中未初始化变量的使用。

静态分析在软件工程中的使用非常普遍,例如 scan-build 是 LLVM 项目提供的一种分析工具,目标是 C、 Objective-C、 C + + 和 Swift; Python 的 black或 Go 的 gofmt 是代码格式化的工具; Rust-analyzer是Rust 的模块化编译器。

静态分析也是其他几个领域的核心。例如,编译器设计,大多数编译器在生成代码之前和之后运行许多单独的静态分析。实际上,可以将编译器大体上看作一个静态分析工具,这个工具生成的数据包括可执行程序以及调试信息。然而,静态分析一般指的是可以与编译器或构建系统一起使用的外部工具。

静态分析有着基本的限制,其局限性意味着静态分析常常局限于逼近程序的真实行为。尽管如此,一个近似值在实践中是非常有用的。

静态分析的过去

静态分析工具是一个程序,通常独立于程序执行机制(如解释器或编译器) ,在独立工具出现之前,静态分析是作为现有程序的一部分出现的。

类型推断算法的第一次发展出现在1958年,这些算法既可以检查程序中声明的值类型,也可以在没有明确声明的情况下推断值的类型。接下来,大量关于分析的研究聚焦于编译器的优化。今天的静态分析工具是在20世纪70年代发展起来的。最早的分析工具是Lint,写于1978年,1979年伴随着 Unix 而发布,用于检查 c 程序的错误。那时的 C编译器执行的正确性检查远远低于现在的编译器,lint 引入了一些流行的分析方式,例如关于可疑类型转换的告警、不可移植的结构、未使用或未初始化的变量等等,这些告警现在通常已经是 c 编译器本身的一部分了。Lint 的影响力巨大,它的名字已经成为许多编程语言静态分析工具的一部分。

随着时间的推移,静态分析已经成为了许多软件开发方法的基本部分。

静态分析的发展

因为语言之间在语法和语义上有很大的差异,大多数静态分析工具都是针对单一语言的。语言的特性对相关分析工具的行为和需求都有着巨大的影响,例如,面向支持字符串运行时代码求值(eval ())的语言如 JavaScript 和 Python,必须要考虑到这些特性。在没有 eval ()的语言中,就不需要考虑这一点。另外,针对高级语言的分析不需要考虑低级内存访问的风险。

如今,有许多方法可以在代码库中引入静态分析。许多版本控制软件服务,无论是免费的还是商业的,都提供了一个集成的静态分析工具平台,当新代码被推送到仓库时,就可以按需执行分析。静态分析工具还与持续集成服务协助,如果分析工具报告有意外结果,则构建过程就会失败。使用现有的分析框架扩展,我们可以编写自己的静态分析工具,例如,scan-build 提供了一个 API,使最终应用能够挂接到 LLVM 的内部进程,并利用 LLVM 的工具链来遍历和分析程序的语法树。

静态分析及其相关语言之间的影响是双向的,静态分析的发展推动了编译器和相关工具的发展,例如Swift语音的出现。Objective-C 内存管理最初是手动引用计数,与 C 编译器相关联的静态分析可以检查是否正确保留和释放内容。ARC的引入,使Objective-C 成为了具有正式内存管理策略的语言,为Swift 的诞生铺平了道路。类似地,类型推理分析促进了 ML 语言家族的发展,并将类型推理引入到缺乏类型推理的语言中,例如C ++ 。

静态分析的应用

静态分析在应用中有几种方式,最直接的分析方法是在其本地的机器上运行分析。许多流行的文本编辑器和 IDE自动集成了静态分析工具,在我们开发软件时直接向提供分析反馈。静态分析一般集成到开发和构建过程中。然而,许多静态分析是看不见的,例如一个编译器本身就是一个静态分析,数十个单独的静态分析联接在一起,生成一个可由计算机执行的程序。甚至,文本编辑器也执行自己的分析,几乎所有的编辑器都使用了语法高亮,这也是一种静态分析,可以产生关于程序中使用的标识符和关键字的语义信息。此外,在开发过程中使用的大部分软件都是静态分析的,包括操作系统乃至 CPU 的微代码。

并非所有的分析在实践中都是可行的。代码库越大,解析和遍历所需的时间就越长。因此,静态分析和被分析的代码库之间是一种军备竞赛。随着代码库变得越来越大,程序员需要更加复杂且高效的分析。

采用静态分析工具的一个障碍是要求人们改变自己的行为,以解释发现的问题和出现的告警。自从 lint 出现以来,工程师一直在努力消除与误报结果相关的告警,通常是在代码中插入”魔法注释”。然而,手工插入这些指令很乏味,工程师通常会选择不使用会产生太多误报的静态分析工具。工程师通过仔细配置给定工具来避免假阳性,而假阴性更难发现,一般通过同时使用多个静态分析工具来降低风险。

静态分析的未来

现代的静态分析工具为代码库提供了强大的洞察力。例如,Linux 内核团队开发了Coccinelle,用于搜索、分析和重写 C的源代码,由于 Linux 内核包含2700多万行代码,因此静态分析工具对于发现 bug 以及对其许多库和模块进行自动更改都至关重要。针对 C语言家族的另一个工具是 Clang scan-build,它提供了许多有用的分析,并为程序员编写自己的分析提供了一个 API。

基于云的工具集成了现有的构建和发布过程,并且可以跨多种编程语言工作。与静态分析有关的高级协议也出现了,语言服务器协议(Language Server Protocol)是一套通用的定义,标准化了分析工具与文本编辑器(如 Emacs 和 VS Code)的接口,确保了分析工具可以与工作流集成。同样,SARIF (Static Analysis Results Interchange Format)为静态分析工具生成的输出提供了一个标准,而以检测安全漏洞为目标的静态分析持续吸引着大家的关注。

随着新的平台、操作系统和编程语言的出现,软件生产的机制变得更加复杂。事实上,软件的复杂性增长速度通常快于工程师管理这种复杂性的能力,这是软件工程和计算机科学面临的主要挑战,而静态分析是最有效的武器之一,产生我们这些从业者应得的知识和洞察力。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 喔家ArchiSelf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 静态分析的过去
  • 静态分析的发展
  • 静态分析的应用
  • 静态分析的未来
相关产品与服务
持续集成
CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档