Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the useful GCC flags for C?

People also ask

What is C flag in GCC?

gcc -c compiles source files without linking.

Which GCC flag is used to enable?

gcc -Wall enables all compiler's warning messages. This option should always be used, in order to generate better code.

Can GCC be used for C?

GNU Compiler Collection (GCC): a compiler suite that supports many languages, such as C/C++ and Objective-C/C++.


Here are mine:

  • -Wextra, -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.


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.


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.


-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.


I'm surprised nobody has said this yet - 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 whilst it's executing.


-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.

  • http://gcc.gnu.org/wiki/Mudflap_Pointer_Debugging

Here's a demo:

$ 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

Not really related to C/C++, but useful anyways :

@file

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

eg:

File : compilerFlags

-Wall

-std=c99

-Wextra

Then compile :

gcc yourSourceFile @compilerFlags