LWN:GCC诊断信息近期改进!
共 2885字,需浏览 6分钟
·
2023-10-31 21:48
关注了就能看到更多这么棒的文章哦~
Recent improvements in GCC diagnostics
By Jonathan Corbet
October 13, 2023
Cauldron
ChatGPT translation
https://lwn.net/Articles/946733/
编译器的主要任务是将源代码转换成计算机可运行的二进制形式。然而,开发人员对于他们的工具,包括编译器,会有更多需求。由于编译器必须理解要翻译的代码,它有很好的机会提供关于代码执行方式以及可能出错的地方的信息。在2023年GNU工具锅会议上,David Malcolm谈到了改进GCC编译器的诊断输出方面的最新工作。
演讲的大部分内容都专注于编译器静态分析器生成的ASCII艺术方式输出的改进。在现有的GCC 13版本中,编译器能够引用源代码,下划线和标记源范围,并提供改进代码的提示。所有这些输出都由一个名为 pretty-print.cc
的模块创建,它具有很多很好的功能,但越来越难以扩展。它不擅长创建二维布局,在处理非ASCII文本和颜色支持方面有不足。
该模块试图基于文本方式来解释分析器发现的潜在代码问题,并 "在某种程度上成功",他说。但它缺乏对开发人员有帮助的空间信息。如果编译器抱怨可能有越界访问,这个访问是朝哪个方向的?是在有效区域之前还是之后,或者可能与之重叠?为了说明这一点,Malcolm展示了这个示例(摘自他的幻灯片):
这个输出描述了潜在的缓冲区溢出并提供了有用的信息,但对于开发人员来说,这可能还不足以可视化地了解真正发生了什么。因此,GCC 14增加了一个图表:
更复杂的情况也可以进行说明;请查看幻灯片以获取其他示例。还将为字符串操作添加更好的图表,以在可能的情况下显示实际的字符串文字以及相应的UTF-8字符串。
所有这些图片都是由一个新的 text-art
模块生成的,它可以执行 pretty-print.cc
提供的一切,还有更多。它处理二维布局和完整的Unicode字符集。支持颜色和其他文本属性,包括 "闪烁",尽管他要求观众实际上不要使用这个功能。它是 "round-trippable",这意味着它的输出可以被解析回来生成一个二维缓冲区;他说这个功能将对未来的图表很有用。为了展示 text-art
可以做什么,他展示了 "最无用的GCC插件":一个棋盘。
当然,还有一些工作要做。其中一个项目是一个新的 #pragma
操作,让GCC绘制一个struct的内存布局,以便开发人员可以看到各个字段将被如何pack起来。另一个是提供SVG格式的输出,尽管他透露他不确定这个功能有多大用处。他说,这两个功能都已经有了 "很粗糙的原型"。
在谈到GCC静态分析器时,Malcolm讲述了一些用于分析C字符串操作的新功能。他实现了一个新的warning,用于可能传递未终止的字符串的操作,但最后还是取消了它,并创建了一个更灵活的模块,能够扫描预期存在的最终null字节。例如,它可以检查格式字符串是否正确终止,还可以检测字符串中的未初始化字节。
他添加了对许多标准字符串函数的语义理解,如 strcat()
, strcpy()
, strlen()
等。分析器现在能够检测会让字符串缓冲区溢出的操作,尽管目前仅适用于固定大小的字符串,但未来将进行更高级的分析。还有一个检查传递给 strcat()
的地址重叠字符串的检查;他说他想使用 restrict
关键字来指示在哪些情况下进行这些检查,但 "没有人真正理解 restrict
做什么"。因此,目前,检查程序只查找在不允许的情况下发生了地址重叠的地方。
他说,未来的计划包括实施一个新的函数属性,指示需要一个以null字节结尾的字符串作为参数。分析器生成的诊断的可视化图表始终有待改进。他还希望添加对更多标准库函数语义的理解,以便进行检查。
分析器目前仅适用于C代码;添加处理C++的能力是一个期望的功能。现在已经存在C++的基本支持,尚未被宣布正式支持,"不要使用它"。他说,最大的问题是它没有exception的概念,并且在使用异常的代码中会搞糊涂了,但还有其他一些问题。有一个谷歌夏令营的学生(Benjamin Priour)正在处理C++,目前仅关注不出现exception的情况。目标是能够在GCC本身上使用分析器(GCC已经转向C++,但不使用exception)。已添加了一个测试套件,分析器代码的大部分已能够处理两种语言。对C++ new
关键字的处理已得到改进。然而,还有很多工作要做。
Priour还参与了另一个与C++有关的项目,是改进了在嵌套的系统头文件集中检测到错误时的输出。在这种情况下,一个简单的错误就可能会生成大量输出。会新增一个新的编译器选项,名为 -fno-analyzer-show-events-in-system-headers
,可以使所有这些输出消失。
尽管有这些改进,Malcolm说,尝试使用分析器处理复杂的C++代码 "仍然会产生无意义的信息"。
在分析器代码本身内部,已建立了一个新的集成测试套件。每个分析器patch都通过构建一整套项目进行测试,包括coreutils、Doom、Git、内核、QEMU等等。发出的警告被捕获并与基线进行比较,以查找回归(或改进)。分析器现在能够使用 alloc_size
函数属性来检查由函数返回的对象的访问。可能会在GCC 14版本中包含的另一个功能是用于潜在出现无限循环的警告。这个检查还没有准备好,它会产生误报,而且运行时间为O(n^{2}),不是最理想的状态。
Malcolm最后提到了一个长期目标:改进与C++模板相关的错误处理。一个错误的拼写错误可能会导致生成大量无用的错误信息。有各种各样的团体试图弄清楚在这种情况下实际上什么信息是有用的。他说,真正的问题是,编译器仍然停留在上世纪70年代,那时建立了批处理交互方式。对于更复杂的错误,开发人员确实需要一种更具交互性的方式来探索情况。
[感谢Linux基金会,LWN的旅行赞助商,支持我参加此活动。]
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~