软件工具通常会提供多种功能可供选择,但正如你所知,并不是所有的功能都能被所有人使用。公平地说,这不是设计错误,因为每个用户都有自己的需求,他们只会在自己的领域内使用该工具。但是,深入了解你使用的工具也是有好处的,因为你永远不知道它的某个特性什么时候会派上用场,为你节省宝贵的时间。举个例子:编译器。一个优秀的编程语言编译器总会提供很多选项,但用户通常只知道和使用其中非常有限的一部分功能。更具体地说,如果您是C语言开发人员并使用Linux作为您的开发平台,那么您很可能会使用gcc编译器,它提供了(几乎)无数的命令行选项列表。你知道你可以告诉gcc保存每个编译阶段的输出吗?您知道用于生成不包含特殊警告的警告的-Wall选项吗?gcc的许多命令行选项并不经常使用,但它们在某些情况下非常有用,例如,当您调试代码时。因此在这篇文章中,我们将介绍几个这样的选项,提供所有必要的细节,并用易于理解的例子来解释它们。但在开始之前,请注意本文所有示例使用的环境:基于Ubuntu16.04LTS操作系统,gcc版本为5.4.0。在每个编译阶段检查中间代码的输出。你知道通过gcc编译C语言代码一般有四个阶段吗?它们是预处理->编译->汇编->链接。在每个阶段之后,gcc都会生成一个临时输出文件,该文件将移交给下一阶段。但是生成的文件都是临时文件,所以我们看不到它们——我们看到的只是我们发出编译命令,然后它生成一个二进制文件或可执行文件,我们可以直接运行。但是比如在预处理阶段,如果你在调试的时候需要看代码是如何处理的,你是怎么做的呢?好消息是gcc编译器提供了相应的命令行选项,您可以在标准编译命令中使用这些选项来获取本来会被编译器移除的中间文件。我们谈论的选项是-save-temps。gcc手册中是这样描述这个选项的:永久存储临时中间文件,将它们放在当前文件夹中并以源文件名命名。因此,使用-c-save-temps编译foo.c会生成foo.ifoo.s和foo.o文件。尽管如今大多数编译器都使用集成的预处理器,但此命令仍会生成经过预处理的输出文件foo.i。当与-x命令行选项一起使用时,-save-temps命令避免覆盖与中间文件具有相同扩展名的输入源文件。在使用-save-temps命令之前,可以通过重命名源文件来获取相应的中间文件。下面是如何使用该选项的示例:gcc-Wall-save-tempstest.c-otest-exec下图显示了该命令的执行结果,验证它确实产生了中间文件:因此,您看到的测试截图中的.i、test.s、test.o文件都是通过-save-temps选项生成的。这些文件分别对应预处理、编译和链接阶段。使您的代码可调试和可分析您可以使用专有工具来调试和分析您的代码。例如,gdb是专门用于调试的工具,而gprof是流行的分析工具。但是您是否知道特定于gcc的命令行选项还可以使您的代码可调试和可分析?让我们开始调试之路吧!为了在代码调试中使用gdb,需要在编译代码时使用gcc编译器提供的-g选项。该选项告诉gcc生成gdb成功调试程序所需的调试信息。如果你想使用这个选项,建议你阅读gcc手册为这个选项提供的详细信息——其中一些在某些情况下可能很关键。例如,这里是手册页的摘录:GCC允许-O选项和-g选项。优化代码的便捷方式有时会产生意想不到的结果:你声明的一些变量可能已经不存在了;控制流可能会突然跳到你没有想到的地方;有些语句可能不会执行,因为它们已经计算出常量结果或者已经保存了值;有些语句可能会在不同的地方执行,因为它们已被移出循环。然而,优化的输出也是可调试的。这允许优化器合理地优化可能有错误的代码。不仅是gdb,使用-g选项编译代码还可以使用Valgrind的内存检测工具,从而充分利用此选项的潜力。有些人可能不知道,mencheck这个工具是程序员用来检测代码是否存在内存泄漏的工具。您可以在此处查看此工具的用法。继续,为了能够在代码分析中使用gprof工具,您需要使用-pg命令行选项编译代码。这会导致gcc生成额外的代码来写入分析信息,这是gprof工具进行代码分析所需要的。gcc手册中提到:编译需要数据的源文件时必须使用该选项,当然链接时也需要使用。要了解有关gprof在分析代码时如何工作的更多信息,您可以转到我们网站特定的教程。注意:-g和-pg选项的使用方式与上一节中-save-temps选项的使用方式类似。结束语相信除了gcc专业人士以外的所有人都能从这篇文章中得到一些启发。试用这些选项,看看它们是如何工作的。同时,期待本教程系列的下一部分,我们将讨论更多有趣和有用的gcc命令行选项。
