What are the useful GCC flags for C?
Asked Answered
P

24

180

Beyond setting -Wall, and setting -std=XXX, what other really useful, but less known compiler flags are there for use in C?

I'm particularly interested in any additional warnings, and/or and turning warnings into errors in some cases to absolutely minimize any accidental type mismatches.

Patrology answered 30/7, 2010 at 22:4 Comment(3)
Well -save-temps, -Wshadow and -fmudflap were the greatest finds I didn't know of, thanks to all.Patrology
Context, as far as I can tell: running gcc -c [flags-go-here] -o myprog.o myprog.c to compile (not link) a C program.Russophobe
Related: Recommended GCC warning options for CNikkinikkie
E
71

Several of the -f code generation options are interesting:

  • -fverbose-asm is useful if you're compiling with -S to examine the assembly output - it adds some informative comments.

  • -finstrument-functions adds code to call user-supplied profiling functions at every function entry and exit point.

  • --coverage instruments the branches and calls in the program and creates a coverage notes file, so that when the program is run coverage data is produced that can be formatted by the gcov program to help analysing test coverage.

  • -fsanitize={address,thread,undefined} enables the AddressSanitizer, ThreadSanitizer and UndefinedBehaviorSanitizer code sanitizers, respectively. These instrument the program to check for various sorts of errors at runtime.

Previously this answer also mentioned -ftrapv, however this functionality has been superseded by -fsanitize=signed-integer-overflow which is one of the sanitizers enabled by -fsanitize=undefined.

Erg answered 31/7, 2010 at 1:35 Comment(3)
For -ftrapv, do have a look here stackoverflow.com/questions/20851061/… .. seems like there's a bug long waiting to get fixed.Valenzuela
Can You Check The Above Comment?Gounod
-ftrapv was essentially superseded by -fsanitize=signed-integer-overflow.Locular
B
159

Here are mine:

  • -Wextra and -Wall: essential.
  • -Wfloat-equal: useful because usually testing floating-point numbers for equality is bad.
  • -Wundef: warn if an uninitialized identifier is evaluated in an #if directive.
  • -Wshadow: warn whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.
  • -Wpointer-arith: warn if anything depends upon the size of a function or of void.
  • -Wcast-align: warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a char * is cast to an int * on machines where integers can only be accessed at two- or four-byte boundaries.
  • -Wstrict-prototypes: warn if a function is declared or defined without specifying the argument types.
  • -Wstrict-overflow=5: warns about cases where the compiler optimizes based on the assumption that signed overflow does not occur. (The value 5 may be too strict, see the manual page.)
  • -Wwrite-strings: give string constants the type const char[length] so that copying the address of one into a non-const char * pointer will get a warning.
  • -Waggregate-return: warn if any functions that return structures or unions are defined or called.
  • -Wcast-qual: warn whenever a pointer is cast to remove a type qualifier from the target type*.
  • -Wswitch-default: warn whenever a switch statement does not have a default case*.
  • -Wswitch-enum: warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration*.
  • -Wconversion: warn for implicit conversions that may alter a value*.
  • -Wunreachable-code: warn if the compiler detects that code will never be executed*.

Those marked * sometimes give too many spurious warnings, so I use them on as-needed basis.

Bikaner answered 31/7, 2010 at 2:10 Comment(6)
Pretty complete list, just want to add one more; -Wformat=2: Extra format checks on printf/scanf functions.Epoch
arent all these implied by -Wall?Algonquian
@chacham15, no, I don't think so. gcc.gnu.org/onlinedocs/gcc/Warning-Options.htmlBikaner
@Alok hmm, maybe its not standard among distributions? I know that on my mbp I have to explicitly turn off -Wwrite-strings because I hate it so much.Algonquian
@chacham15, maybe. But the description for -Wwrite-strings specifically says it's not a part of -Wall: gcc.gnu.org/onlinedocs/gcc/…. Maybe something else in your setup is setting that flag? Or maybe you're compiling C++?Bikaner
-Wunreachable-code's functionality has been removed (however gcc won't warn if the option is still being used...) gcc.gnu.org/ml/gcc-help/2011-05/msg00360.htmlMarquez
E
71

Several of the -f code generation options are interesting:

  • -fverbose-asm is useful if you're compiling with -S to examine the assembly output - it adds some informative comments.

  • -finstrument-functions adds code to call user-supplied profiling functions at every function entry and exit point.

  • --coverage instruments the branches and calls in the program and creates a coverage notes file, so that when the program is run coverage data is produced that can be formatted by the gcov program to help analysing test coverage.

  • -fsanitize={address,thread,undefined} enables the AddressSanitizer, ThreadSanitizer and UndefinedBehaviorSanitizer code sanitizers, respectively. These instrument the program to check for various sorts of errors at runtime.

Previously this answer also mentioned -ftrapv, however this functionality has been superseded by -fsanitize=signed-integer-overflow which is one of the sanitizers enabled by -fsanitize=undefined.

Erg answered 31/7, 2010 at 1:35 Comment(3)
For -ftrapv, do have a look here stackoverflow.com/questions/20851061/… .. seems like there's a bug long waiting to get fixed.Valenzuela
Can You Check The Above Comment?Gounod
-ftrapv was essentially superseded by -fsanitize=signed-integer-overflow.Locular
E
56

Always use -O or above (-O1, -O2, -Os, etc.). At the default optimization level, gcc goes for compilation speed and doesn't do enough analysis to warn about things like unitialized variables.

Consider making -Werror policy, as warnings that don't stop the compilation tend to be ignored.

-Wall pretty much turns on the warnings that are very likely to be errors.

Warnings included in -Wextra tend to flag common, legitimate code. They may be useful for code reviews (though lint-style programs find a lot more pitfalls are more flexible), but I wouldn't turn them on for normal development.

-Wfloat-equal is a good idea if the developers on the project are unfamiliar with floating point, and a bad idea if they are.

-Winit-self is useful; I wonder why it's not included in -Wuninitialized.

-Wpointer-arith is useful if you have mostly-portable code that doesn't work with -pedantic.

Equalizer answered 30/7, 2010 at 22:29 Comment(0)
U
41

The most useful flag, as far as I'm concerned, is -g which puts debugging information into the executable such that you can debug it and step through the source (unless you're proficient and reading assembly and like the stepi command) of a program while it's executing.

Unite answered 30/7, 2010 at 22:23 Comment(0)
U
41

-save-temps

This leaves behind the results of the preprocessor and the assembly.

The preprocessed source is useful for debugging macros.

The assembly is useful for determining what optimizations went into effect. For instance, you may want to verify that GCC is doing tail call optimization on some recursive functions, as without it you can potentially overflow the stack.

Uralian answered 3/8, 2010 at 18:58 Comment(1)
I did wonder how you got it to do that... I've always just asked gcc to dump the assembly if I needed it.Unite
A
36

-fmudflap—adds runtime checks to all risky pointer operations to catch UB. This effectively immunizes your program again buffer overflows and helps to catch all kinds of dangling pointers.

See Mudflap Pointer Debugging

Here's a demo:

FIle mf.c

int main()
{
  int a[10];
  a[10] = 1; // <-- Oh noes, line 4
}

Compilation and execution

gcc -fmudflap mf.c -lmudflap
./a.out

Output:

*******
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
Ancell answered 3/8, 2010 at 18:50 Comment(3)
Hmmm, mudflap seems pretty nasty :PPatrology
-fmudflap is no longer supported since GCC 4.9, you get warning: switch '-fmudflap' is no longer supported. It was superseded by AddressSanitizer.Helm
Yep, the last version with it included was 4.8.5 (released 2015-06-23). GCC 4.9.0 was released 2014-04-22 (note overlapping dates).Nikkinikkie
V
27

It is not really related to C/C++, but it is useful anyway:

@file

Put all the good flags in previous answers (which you all have specified) in a 'file', and use this above flag to use all the flags in that file together.

for example:

File : compilerFlags

-Wall

-std=c99

-Wextra

Then compile:

gcc yourSourceFile @compilerFlags
Veracity answered 15/7, 2013 at 6:47 Comment(0)
R
17

-march=native to produce optimized code for the platform (=chip) on which you are compiling.

Remonstrate answered 31/7, 2010 at 7:33 Comment(1)
If you are compiling for non-native machines where you don't know the target, you can use mtune=xxx which optimizes without using instruction sets. For example mtune=generic is kept up to date with the "average" case processors.Planck
A
16

If you need to know the preprocessor flags that are predefined by the compiler:

echo | gcc -E -dM -

Armchair answered 31/7, 2010 at 13:46 Comment(0)
L
15

It's not really helpful for detecting errors, but the rarely mentioned -masm=intel option makes using -S to inspect the assembly output much, much nicer.

AT&T assembly syntax hurts my head far too much.

Leora answered 4/8, 2010 at 6:15 Comment(2)
The difference between AT&T and Intel to me is the difference between C# and Java. Just syntax. Both awful. :)Patrology
+1 @michael for making gcc use intel syntax instead of the god awful at&t. Inspecting assembly uses enough brain cycles -- no need to waste brain cycles that src goes before dest in opcodes. Now if only gcc supports the __asm {} inline like other compilers we're all set!Almsgiver
P
11

Here's a great flag that hasn't been mentioned:

-Werror-implicit-function-declaration

Give a error whenever a function is used before being declared.

Patrology answered 14/8, 2010 at 15:59 Comment(1)
Since GCC 4.6 (released 2011-03-25), this has been -Werror=implicit-function-declaration instead (or an alias?). -Wimplicit-function-declarationNikkinikkie
A
10

My makefile typically contains

CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
...
g++ $(CFLAGS) -o junk $<
gcc $(CFLAGS) -o $@ $<
rm -f junk

The most important of these options have been discussed before, so I'll point out the two features that have not been pointed out yet:

Even though I'm working on a codebase that needs to be plain C for portability to some platform that still has no decent C++ compiler, I do an "extra" compile with the C++ compiler (in addition to the C compiler). That has 3 benefits:

  1. the C++ compiler occasionally gives me better warning messages than the C compiler.
  2. The C++ compiler accepts the -Weffc++ option, which occasionally gives me some useful tips, which I would miss out on if I only compiled it in plain C.
  3. I can keep the code relatively easy to port to C++, avoiding a few boundary conditions where plain C code is invalid C++ code (such as defining a variable named "bool").

Yes, I'm a hopelessly optimistic Pollyanna that keeps thinking that surely any month now that one platform will either be declared obsolete, or gain a decent C++ compiler, and we can finally switch to C++. In my mind, it is inevitable—the only question is whether that happens before or after management finally issues everyone a pony. :-)

Agony answered 30/7, 2010 at 22:4 Comment(3)
A good point with writing it as C++, I consider this often. (subset naturally)Patrology
I should point out that C being deprecated in favor of C++ will never happen, sorry :)Patrology
consider -o /dev/null instead of rm -f junkOvermatter
C
9

-Wstrict-prototypes -Wmissing-prototypes

Cisco answered 30/7, 2010 at 22:32 Comment(2)
And -Wold-style-definition if you have to deal with recidivists who think K&R style functions are a good idea, even with prototyped declarations. (I have to deal with people like that. It really annoys me when I find new code written in K&R. It is bad enough having legacy K&R stuff that isn't fixed, but new code! Grump!!!)Snooker
-Wold-style-definitionNikkinikkie
C
8
man gcc

The manual is full of interesting flags with good descriptions. However, -Wall will probably make GCC as verbose as possible. If you want more interesting data, you should take a look at Valgrind or some other tool for checking for errors.

Colman answered 30/7, 2010 at 22:9 Comment(2)
It is loooooooooooooooooooooooooooooooong, though. man gcc | nl reports over 11000 lines. That's more than the infamous bash manpage!Some
Thank god they crammed it into a man page, instead of one of those godawful unnavigateable "info" pages.Patrology
M
7

There is -Werror, which treats all warnings as errors and stops the compilation. The gcc manual page explains every command line switch for your compiler.

Mutton answered 30/7, 2010 at 22:9 Comment(1)
@Matt Joiner: Since you didn't mention which machine architecture you are using, the gcc flags might be different between yours and whatever link anybody might suggest. This is why manual pages are supplied with your software.Mutton
S
6

Well, -Wextra should be standard, too. -Werror turns warnings into errors (which can be very annoying, especially if you compile without -Wno-unused-result). -pedantic in combination with std=c89 gives you additional warnings if you use C99 features.

But that's about it. You cannot tune a C compiler into something more type-safe than C itself.

Selina answered 30/7, 2010 at 22:14 Comment(0)
U
6

-M* family of options.

These let you write make files that automatically figure out what header files your C or C++ source files should depend on. GCC will generate make files with this dependency information, and then you -include them from your primary make file.

Here's an example of an extremely generic makefile using -MD and -MP that will compile a directory full of C++ source and header files, and figure out all the dependencies automatically:

CPPFLAGS += -MD -MP
SRC = $(wildcard *.cpp)

my_executable: $(SRC:%.cpp=%.o)
        g++ $(LDFLAGS) -o $@ $^

-include $(SRC:%.cpp=%.d)

Here's a blog post that discusses it in more depth: Automatically generate makefile dependencies

Uralian answered 6/1, 2012 at 21:47 Comment(0)
D
5

I found this question looking for a flag to fix a specific issue. I don't see it on here, so I'll add one that was just stumping me on my post:

The -Wformat=2 flag

-Wformat => Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified...

And the really important part about it (according to the GCC manual):

-Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall.`

So, just because you have -Wall doesn't mean you have it all. ;)

Decahedron answered 25/10, 2012 at 12:56 Comment(0)
A
4

I sometimes use -s for a much smaller executable:

-s
    Remove all symbol table and relocation information from the executable.

Source: Options for Linking

Anguiano answered 31/7, 2010 at 0:38 Comment(2)
you should just run strip on your binary, this way you can have a binary with debug information, remove it later for distribution.Unwitting
Yes, strip works too but -s can be quicker and easier, though it's not as elaborate as running stripAnguiano
H
4

-Wfloat-equal

From char * const argv[]:

One of the other new warnings that I like is the -Wfloat-equal. That one warns whenever you [have] a floating-point number in an equality condition. That's briliant! [sic] If you have every [sic] programmed a computer graphics or (worse:) computational geometry algorithm, you know that no two floats ever match with equality...

Hippocampus answered 31/7, 2010 at 13:6 Comment(2)
My floats do match with equality, as I know what I'm doing.Leopoldine
@RolandIllig I don't (sobs uncontrollably while adding 0.1 and 0.2 over and over again on a piece of paper).Vieira
P
3

While this answer may be slightly off-topic and the question is a worthy +1 from me, since

I'm particularly interested in any additional warnings, and/or and turning warnings into errors in some cases to absolutely minimize any accidental type mismatches.

there is a tool that should catch out all errors and potential errors that may not be obvious. There's Splint which, IMHO, does a way better job in catching out errors compared to GCC or any other compiler for that matter. That is a worthy tool to have in your tool chest.

Static checking via a lint-type of tool such as Splint, should have been part of a compiler toolchain.

Penzance answered 9/8, 2010 at 15:4 Comment(1)
It always shows an error cannot file preprocessor file in C:\include , i am not sure what to doGounod
D
2

I'm particularly interested in any additional warnings,

In addition to -Wall, the -W or -Wextra option (-W works with older versions of gcc as well as newer ones; more recent versions support the alternative name -Wextra, which means the same thing, but is more descriptive) enables various additional warnings.

There are also even more warnings which are not enabled by either of those, generally for things that are more questionably bad. The set of available options is dependent on which gcc version you are using - consult man gcc or info gcc for details, or see the online documentation for the particular gcc version you're interested in. And -pedantic issues all warnings required by the particular standard being used (which depends on other options such as -std=xxx or -ansi) and complains about use of gcc extensions.

and/or and turning warnings into errors in some cases to absolutely minimize any accidental type mismatches.

-Werror turns all warnings into errors. I don't think gcc lets you do that selectively for particular warnings, though.

You'll probably find that you have to be selective about which warnings are enabled on a per-project basis (especially if you use -Werror), as header files from external libraries can trip some of them. (-pedantic in particular tends to be unhelpful in this respect, in my experience.)

Doer answered 30/7, 2010 at 22:10 Comment(1)
"I don't think gcc lets you do that selectively for particular warnings, though." Actually, you can with -Werror=some-warning.Kirbie
B
1
  • -Wmissing-prototypes: If a global function is defined without a previous prototype declaration.
  • -Wformat-security: Warns about uses of format functions that represent possible security problems. At present, this warns about calls to printf and scanf functions where the format string is not a string literal and there are no format arguments
Blowup answered 7/2, 2018 at 9:35 Comment(0)
M
1

Actually, I'd like to keep my C code cross-platform. I use CMake, and I put the provided cflags into CMakeLists.txt like:

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()
Meilen answered 27/11, 2018 at 11:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.