Answers:
几个-f
代码生成选项很有趣:
该-ftrapv
函数将导致程序在有符号整数溢出(在C中通常为“未定义的行为”)中止。
-fverbose-asm
如果要进行编译-S
以检查程序集输出,则很有用-它添加了一些有用的注释。
-finstrument-functions
在每个函数入口和出口点添加代码以调用用户提供的概要分析函数。
-ftrapv
,请在这里看看stackoverflow.com/questions/20851061/… ..似乎有一个等待修复的错误。
这是我的:
-Wextra
,-Wall
:是必不可少的。-Wfloat-equal
:很有用,因为通常测试浮点数是否相等是不好的。-Wundef
:警告是否在#if
指令中评估了未初始化的标识符。-Wshadow
:每当局部变量遮盖另一个局部变量,参数或全局变量或遮盖内置函数时发出警告。-Wpointer-arith
:警告是否取决于函数或函数的大小void
。-Wcast-align
:在投射指针时发出警告,以增加目标的所需对齐方式。例如,警告是否将a char *
强制转换为int *
只能在两字节或四字节边界访问整数的计算机上。-Wstrict-prototypes
:警告是否在未指定参数类型的情况下声明或定义了函数。-Wstrict-overflow=5
:警告编译器基于没有发生符号溢出的假设进行优化的情况。(值5可能太严格,请参见手册页。)-Wwrite-strings
:给字符串常量指定类型const char[
长度,]
以便将一个地址复制到非const char *
指针中将得到警告。-Waggregate-return
:警告是否定义或调用了任何返回结构或联合的函数。-Wcast-qual
:当强制转换指针以从目标类型*中删除类型限定符时发出警告。-Wswitch-default
:当switch
语句没有default
案例*时警告。-Wswitch-enum
:当一条switch
语句具有枚举类型的索引并且缺少case
该枚举*的一个或多个命名代码时,发出警告。-Wconversion
:警告可能会改变值*的隐式转换。-Wunreachable-code
:警告如果编译器检测到代码将永远不会执行*。带有*的标记有时会给出过多的虚假警告,因此我会根据需要使用它们。
-Wformat=2
:对printf / scanf功能进行额外的格式检查。
-Wall
吗?
-Wwrite-strings
因为我非常讨厌它。
-Wwrite-strings
具体描述是它不属于-Wall
:gcc.gnu.org/onlinedocs/gcc/…。也许您的设置中还有其他设置该标志的方法?还是您正在编译C ++?
始终使用-O
或上述(-O1
,-O2
,-Os
等等)。在默认优化级别,gcc会提高编译速度,并且不会进行足够的分析以警告诸如变量化之类的问题。
考虑制定-Werror
策略,因为不会停止编译的警告会被忽略。
-Wall
几乎打开了很可能是错误的警告。
其中包含的警告-Wextra
往往会标记通用的合法代码。它们可能对代码审查很有用(尽管lint风格的程序发现很多陷阱更灵活),但是我不会在正常开发中打开它们。
-Wfloat-equal
如果项目的开发人员不熟悉浮点数,则是个好主意,如果不熟悉,则是个坏主意。
-Winit-self
是有用的;我想知道为什么它不包含在中-Wuninitialized
。
-Wpointer-arith
如果您的大多数便携式代码都无法使用,则此功能非常有用-pedantic
。
令我惊讶的是-g
,到目前为止还没有人说过-就我而言,最有用的标志是将调试信息放入可执行文件中,以便您可以调试它并遍历源代码(除非您精通并阅读了汇编和stepi
程序执行时的命令)。
-fmudflap-将运行时检查添加到所有有风险的指针操作中以捕获UB。这有效地使您的程序再次免疫缓冲区溢出,并有助于捕获各种悬空指针。
这是一个演示:
$ cat mf.c
int main()
{
int a[10];
a[10]=1; // <-- o noes, line 4
}
$ gcc -fmudflap mf.c -lmudflap
$ ./a.out
*******
mudflap violation 1 (check/write): time=1280862302.170759 ptr=0x7fff96eb3d00 size=44
pc=0x7f3a575503c1 location=`mf.c:4:2 (main)'
/usr/lib/libmudflap.so.0(__mf_check+0x41) [0x7f3a575503c1]
./a.out(main+0x90) [0x400a54]
/lib/libc.so.6(__libc_start_main+0xfd) [0x7f3a571e2c4d]
Nearby object 1: checked region begins 0B into and ends 4B after
mudflap object 0xf9c560: name=`mf.c:3:6 (main) a'
bounds=[0x7fff96eb3d00,0x7fff96eb3d27] size=40 area=stack check=0r/3w liveness=3
alloc time=1280862302.170749 pc=0x7f3a57550cb1
number of nearby objects: 1
-fmudflap
从GCC 4.9开始不再支持warning: switch '-fmudflap' is no longer supported
。它已由AddressSanitizer取代。
与C / C ++无关,但仍然很有用:
@file
将上面所有好的标记(您都已指定)放入“文件”中,并使用上面的标记将文件中的所有标记一起使用。
例如:
文件:编译器标记
-壁
-std = c99
-Wextra
然后编译:
gcc yourSourceFile @compilerFlags
-march=native
为要在其上编译的平台(=芯片)产生优化的代码
如果您需要了解编译器预定义的预处理器标志,请执行以下操作:
echo | gcc -E -dM -
我的makefile通常包含
CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
...
g++ $(CFLAGS) -o junk $<
gcc $(CFLAGS) -o $@ $<
rm -f junk
这些选项中最重要的选项已经在前面讨论过,因此,我将指出尚未指出的两个功能:
即使我正在开发一个代码库,该代码库需要使用纯C语言才能移植到仍没有合适的C ++编译器的某个平台,但我还是对C ++编译器(除了C编译器)进行了“额外”编译。有3个好处:
是的,我是一个无可救药的乐观主义者,她一直想肯定现在某个平台将被宣布淘汰或获得一个不错的C ++编译器,我们终于可以切换到C ++了。在我看来,这是不可避免的-唯一的问题是这是在管理层最终向所有人发出小马之前还是之后。:-)
-Wstrict-prototypes -Wmissing-prototypes
-Wold-style-definition
如果您不得不与认为K&R样式函数是个好主意的累犯(即使使用原型声明)打交道,(我必须与那样的人打交道。当我找到用K&R编写的新代码时,这真的让我很烦。拥有不固定的旧K&R东西,但是有新代码,这很糟糕!很糟糕!!)
-M*
系列选项。
这些使您可以编写make文件,这些文件可以自动确定您的c或c ++源文件应使用哪些头文件。GCC将使用此依赖项信息生成make文件,然后-在主make文件中包括它们。
这是一个使用-MD和-MP的极其通用的makefile的示例,该文件将编译一个包含c ++源文件和头文件的目录,并自动找出所有依赖项:
CPPFLAGS += -MD -MP
SRC = $(wildcard *.cpp)
my_executable: $(SRC:%.cpp=%.o)
g++ $(LDFLAGS) -o $@ $^
-include $(SRC:%.cpp=%.d)
这是一篇博客文章,对它进行了更深入的讨论:http : //www.microhowto.info/howto/automatically_generate_makefile_dependencies.html
有-Werror
,它将所有警告视为错误并停止编译。该gcc
手册页说明了你的编译器的每个命令行开关。
gcc
标志以及任何可能暗示的链接之间的标志可能会有所不同。这就是软件随附手册页的原因。
-Wfloat-equal
来自:http : //mces.blogspot.com/2005/07/char-const-argv.html
我喜欢的其他新警告之一是-Wfloat-equal。每当您在相等条件下[具有]浮点数时,都会发出警告。太棒了!如果每个人都编写了计算机图形学或(更糟糕的是)计算几何算法,那么您将知道没有两个浮点数相等。
我发现此线程正在寻找一个标志来解决特定的问题,在这里看不到它,因此我将添加一个只是在我的帖子上绊倒我的标志:
该-Wformat=2
标志
-Wformat
=>检查对printf
和scanf
等的调用,以确保提供的参数具有适合于指定格式字符串的类型...
以及真正重要的部分(根据GCC手册):
-Wformat
包含在中-Wall
。在过去的检查中,选择格式的某些方面更多的控制-Wformat-y2k
,-Wno-format-extra-args
,-Wno-format-zero-length
,-Wformat-nonliteral
,-Wformat-security
,和-Wformat=2
可用,但不包括在-Wall.`
因此,仅仅因为拥有拥有权-Wall
并不意味着拥有全部。;)
有时-s
,我会使用较小的可执行文件:
-s
Remove all symbol table and relocation information from the executable.
资料来源:http : //gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
strip
在二进制文件上运行,这样您就可以拥有一个带有调试信息的二进制文件,稍后将其删除以进行分发。
strip
也-s
可以工作,但可以更快,更轻松,尽管它不像运行时那么复杂strip
虽然这个答案可能有点题外话,但这个问题对我来说值得+1,因为
我对任何其他警告和/或在某些情况下将警告转换为错误以最大程度地减少任何意外的类型不匹配特别感兴趣。有应该赶出来的工具所有的错误和潜在的错误,可能不是很明显,有夹板,其恕我直言,做一个更好的方式作业相比,海湾合作委员会或任何其他编译器为物拦截出错误。那是您的工具箱中值得拥有的工具。
通过诸如皮夹之类的绒毛类型的工具进行的静态检查应该已经属于编译器工具链的一部分。
我对任何其他警告特别感兴趣,
除了之外-Wall
,-W
or -Wextra
选项(-W
适用于旧版本的gcc和较新版本的gcc;适用于gcc的替代名称-Wextra
,这意味着同一件事,但更具描述性)支持各种其他警告。
甚至还有一些警告都没有启用,通常是针对更可疑的问题。可用选项集取决于您使用的gcc版本-请咨询man gcc
或info gcc
了解详细信息,或查看您感兴趣的特定gcc版本的在线文档。并-pedantic
发出所使用的特定标准要求的所有警告(具体取决于在其他选项(例如-std=xxx
或-ansi
)上,并抱怨使用gcc扩展名。
和/或在某些情况下将警告变成错误,以最大程度地减少任何意外的类型不匹配。
-Werror
将所有警告变为错误。我不认为gcc可以让您有选择地针对特定警告进行操作。
您可能会发现必须对每个项目启用哪些警告(尤其是使用-Werror
)进行选择,因为来自外部库的头文件可能会使其中一些警告失效。(-pedantic
根据我的经验,这在这方面尤其无济于事。)
-Werror=some-warning
。
-Wmissing-prototypes
:如果在没有先前原型声明的情况下定义了全局函数。-Wformat-security
:警告使用代表可能的安全问题的格式功能。目前,这会警告有关在格式字符串不是字符串文字且没有格式参数的情况下对printf
和scanf
函数的调用-Werror=return-type
:当函数在gcc中没有返回值时,强制执行错误。它/we4716
在Visual Studio中。
-Werror=implicit-function-declaration
:在未定义/未使用功能的情况下强制执行错误。它/we4013
在Visual Studio中。
-Werror=incompatible-pointer-types
:当指针的类型与预期的指针类型不匹配时,将发生Enfore错误。它/we4133
在Visual Studio中。
实际上,我想保持C代码跨平台,并使用CMake,然后将提供的cflags放入CMakeLists.txt中,如下所示:
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4013 /we4133 /we4716")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Werror=return-type")
endif()
-save-temps
,-Wshadow
而且-fmudflap
是我不知道的最伟大的发现,感谢所有。