scan-build 或 Clang 静态分析器能否在 link 时间发现问题?
Can scan-build or Clang static analyzer discover problems at link time?
在重新审视我编写的一些代码时,我注意到测试脚本中的构建命令没有正确调用 scan-build
命令。修订版的形成已经准备就绪,但我对 scan-build
和 Clang 静态分析器的功能有一些疑问。
分析器能否在link时间发现错误?怎么做?
比如在单个源文件中,很容易发现内存分配错误(leak、double-free、free-after-use等),但是通过接口是否还能发现这些错误在另一个翻译单元中实现的功能?
我已经写了 2 个文件来测试它是否可以做到这一点,但显然它不能。
/* memlib.c */
#include <stdlib.h>
void *foo_alloc(int len) { return malloc(len * 4); }
void foo_dealloc(void *foo) { return free(foo); }
/* mem-main.c */
void *foo_alloc(int len);
void foo_dealloc(void *foo);
int main()
{
int *p;
p = foo_alloc(2);
p[1] = 32;
p = foo_alloc(1);
p[0] = 54;
foo_dealloc(p);
p[0] = 47;
foo_dealloc(p);
return 0;
}
编译命令:
scan-build sh -c '$CC "$@"' foo -o mem-main mem-main.c memlib.c
我正在使用 PyPI 中的 scan-build
,但我认为这几乎无关紧要,因为它只是一个程序驱动程序。
附带说明一下,我愿意接受可以执行 link 时间分析的工具建议。
Clang 实验性支持跨翻译单元分析。请参阅 Cross Translation Unit (CTU) Analysis 的 Clang 文档。但是,如链接文档中所述,它目前 (2022-05-23) 是一个相当混乱的提议。基本步骤总结如下:
- 使用
clang++ -emit-ast
为每个翻译单元 (TU) 创建 .ast
个文件。
- 使用
clang-extdef-mapping
列出每个 TU 中的定义。
- 使用
sed
(!) 对定义列表文件进行 ad-hoc 修复,具体来说,将“.cpp”更改为“.cpp.ast”并将文件路径更改为亲戚。
- 运行这样分析:
$ clang++ --analyze \
-Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true \
-Xclang -analyzer-config -Xclang ctu-dir=. \
-Xclang -analyzer-output=plist-multi-file \
main.cpp
有用吗? Vince Bridgers 在 2020 年 LLVM 聚会上的演讲 Using the Clang Static Analyzer 幻灯片 25 显示,cross-translation-unit 分析将五个代码库的发现数量大约翻了一番。一些发现也丢失了,但这将是丢失的误报(好)和丢失的真阳性(坏)的混合,并且该演示文稿没有进一步详细说明。 (不过,我的猜测是大多数都是丢失的 FP。)
关于工具推荐,商业静态分析工具与开源工具的主要区别之一是更准确的 inter-procedural 和 cross-translation-unit 分析。如果对此特别感兴趣,您可能需要查看可用的商业工具。 (披露:我以前曾在一家商业静态分析供应商工作,并且有相关的持续经济利益。)
在重新审视我编写的一些代码时,我注意到测试脚本中的构建命令没有正确调用 scan-build
命令。修订版的形成已经准备就绪,但我对 scan-build
和 Clang 静态分析器的功能有一些疑问。
分析器能否在link时间发现错误?怎么做?
比如在单个源文件中,很容易发现内存分配错误(leak、double-free、free-after-use等),但是通过接口是否还能发现这些错误在另一个翻译单元中实现的功能?
我已经写了 2 个文件来测试它是否可以做到这一点,但显然它不能。
/* memlib.c */
#include <stdlib.h>
void *foo_alloc(int len) { return malloc(len * 4); }
void foo_dealloc(void *foo) { return free(foo); }
/* mem-main.c */
void *foo_alloc(int len);
void foo_dealloc(void *foo);
int main()
{
int *p;
p = foo_alloc(2);
p[1] = 32;
p = foo_alloc(1);
p[0] = 54;
foo_dealloc(p);
p[0] = 47;
foo_dealloc(p);
return 0;
}
编译命令:
scan-build sh -c '$CC "$@"' foo -o mem-main mem-main.c memlib.c
我正在使用 PyPI 中的 scan-build
,但我认为这几乎无关紧要,因为它只是一个程序驱动程序。
附带说明一下,我愿意接受可以执行 link 时间分析的工具建议。
Clang 实验性支持跨翻译单元分析。请参阅 Cross Translation Unit (CTU) Analysis 的 Clang 文档。但是,如链接文档中所述,它目前 (2022-05-23) 是一个相当混乱的提议。基本步骤总结如下:
- 使用
clang++ -emit-ast
为每个翻译单元 (TU) 创建.ast
个文件。 - 使用
clang-extdef-mapping
列出每个 TU 中的定义。 - 使用
sed
(!) 对定义列表文件进行 ad-hoc 修复,具体来说,将“.cpp”更改为“.cpp.ast”并将文件路径更改为亲戚。 - 运行这样分析:
$ clang++ --analyze \
-Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true \
-Xclang -analyzer-config -Xclang ctu-dir=. \
-Xclang -analyzer-output=plist-multi-file \
main.cpp
有用吗? Vince Bridgers 在 2020 年 LLVM 聚会上的演讲 Using the Clang Static Analyzer 幻灯片 25 显示,cross-translation-unit 分析将五个代码库的发现数量大约翻了一番。一些发现也丢失了,但这将是丢失的误报(好)和丢失的真阳性(坏)的混合,并且该演示文稿没有进一步详细说明。 (不过,我的猜测是大多数都是丢失的 FP。)
关于工具推荐,商业静态分析工具与开源工具的主要区别之一是更准确的 inter-procedural 和 cross-translation-unit 分析。如果对此特别感兴趣,您可能需要查看可用的商业工具。 (披露:我以前曾在一家商业静态分析供应商工作,并且有相关的持续经济利益。)