15 ms·
My favorite C compiler flags during development
- cratermoon 3y agoI worked with a programmer who, rather than fixing his code to address the problems these warnings are intended to catch, would sprinkle his code with #pragma or whatever incantation necessary to cause the compiler to ignore the problem code in that specific case. Thus when the automated builds ran, even with warnings on, it would never flag his bad code. I get that sometimes there are circumstances where the warning is a false positive, as the article mentions, so these escape hatches are useful. It's not the case with my former co-worker who seemed to reflexively use these escape hatches whenever he didn't understand why the compiler didn't like his code. It didn't help that he was dependent on his IDE to hold his hand. I suspect today he'd just let one of the LLMs write his code for him.
- andrewmcwatters 3y agoYuck. I think we all know many developers who do this, too.
- yjftsjthsd-h 3y agoI would expect forcibly overriding warnings to be a massive red flag in code review? Like, what company cares enough to care about warnings in CI but not catch people bypassing that check?
- becquerel 3y agoHaha. Hahahaha. Let's just say that there are equivalents to 'security theatre' in this area as well.
- sgerenser 3y agoEnvironments where people do stuff like that usually don’t have code review.
- yjftsjthsd-h 3y agoIf they don't even have code reviews, why do they care about a few warnings in CI?
- zelphirkalt 3y agoBlindfold oriented programming. Or: Learning resistant attitude.
- diydsp 3y agowow -g3 is a great-looking one. can't wait to try it out.
- bigdict 3y agoI recommend `-fanalyzer` with GCC. I haven't found out how to use Clang's static analyzer. GCC now has this elaborate (kind of beautiful) way of highlighting a path through your code which leads to a potential oopsie like use after free. `-fno-omit-frame-pointer` has been useful for profiling using perf.
- bmurray7jhu 3y agoI also like using `-fanalyzer-transitivity` to force the static analyzer to treat constraints as transitive.
- bigdict 3y agoCan you explain what that is? This isn't included under `-fanalyzer`looks like.
- bmurray7jhu 3y agoThe flag applies the transitive property[1] when propagating constraints. This gives more accurate results, but at the cost of analyzer speed. if (4 < x) { if (x < y) { if (y == 0) { // Unreachable since the above three conditions cannot // all be true at the same time (without multithreading). } } } For a more detailed explanation, see [2]. (Also the inspiration for the above example.) [1] https://en.m.wikipedia.org/wiki/Transitive_relation https://en.m.wikipedia.org/wiki/Transitive_relation [2] https://github.com/gcc-mirror/gcc/commit/50ddbd0282e06614b29f0d3f3be5fbe70085a8bd https://github.com/gcc-mirror/gcc/commit/50ddbd0282e06614b29...
- bigdict 3y agoI see, so you are giving it more inference power.
- yaantc 3y agoAs I understand it the Clang static analyzer is not intended to be used directly. It's best to use it through CodeChecker, which provide high level commands and do the low level calls to the Clang SA (and also Clang tidy). In particular if you want whole project analysis (CTU, cross translation units analysis) CC will do the all the needed calls in a single "analyze" command. [1] https://codechecker.readthedocs.io/en/latest/ https://codechecker.readthedocs.io/en/latest/
- lumb63 3y agoI used to have an environment variable defined $W_REALLY_ALL that turned on, really, all the warnings. It always drove me nuts that -Wall didn’t turn them all on and even -Wextra was insufficient. There are really very few false positives in the environments I’ve worked.
- HexDecOctBin 3y agoClang has -Weverything that I almost always turn on.
- spc476 3y agoAnd then you get warnings about structures being padded and warnings about structures not being padded.
- Longhanks 3y agoEasy to opt out via -Wno-padding. I strongly prefer clang‘s -Weverything -Wno-c++98compat -Wno-c++98-compat-pedantic -Wno-padded to gcc‘s -Wall -Wextra -Wyes-really-every-single-one -Walso-this -Wjust-turn-it-all-on-please -Walso-this-obscure -Wetc -Ware-you-getting-it
- account42 3y agoExcept if you already have all the flags for GCC then adding a few more for Clang-specific warnings isn't much of a problem.
- kevin_thibedeau 3y agoA lot of them are excessively pedantic. It is extremely for callbacks to have unused arguments. There is no point in writing extra code just to nullify ineffectual warnings. These are tools that serve us not the other way around.
- lumb63 3y ago
- deleted 3y ago[deleted]
- thatsadude 3y agoGood read, I often have to run code step by step to catch accidental double promotion in dsp functions.
- teo_zero 3y agoGood advise. How do you usually define different sets of flags (for debugging, for production...) in your Makefile?
- flohofwoe 3y agoMeta build systems like cmake allow defining different build types with their own compile settings. I wouldn't recommend using 'raw' Makefiles directly for C/C++ development.
- SleepyMyroslav 3y agoPeople do not write makefiles anymore. At least not by hand. Typical AAA gamedev project has at least 4 targets defined in the build system of choice. Each target gets a set of flags for each platform. Typically there are ways to define common sets of flags and use them in the specific target. Half jokingly, choosing build system for a project is a very important step and one of things that kills desire to do C or C++ projects on the side. The article is a very friendly description of at least a decade of experience. Debugging build systems that do a lot of things ( unity files, caching, multiplatform and distributed builds ) has become an art in itself. Personally I prefer to capture commandlines that are passed to compiler as result to make sure that options are correct.
- saagarjha 3y ago…? Plenty of people write makefiles by hand. ./configure && make && make install is still a common method of doing build systems, even though there are a lot of new ways to also do builds now.
- cultureswitch 3y agoIt is a common and terrible method, only surviving out of general familiarity with the abomination that is autotools.
- saagarjha 3y ago
- pjmlp 3y ago> Every beginner tutorial ought to be using sanitizers from page 1 where they teach how to compile a program with gcc. This right there.
- saagarjha 3y agoIt’s kind of amazing how many university programs teach C(++) without mentioning this at all.
- pjmlp 3y agoYeah, unfortunely quality teaching is seldom widespread in good quantities.
- sametmax 3y agoAnd it's not going to improve with ChatGPT around: https://substack.com/profile/135747695-nobody-has-time-for-python/note/c-15383958 https://substack.com/profile/135747695-nobody-has-time-for-p... Also the problem goes both way. I often see people trying to learn React with little grasp of JS, or Django like it's a language, and not something based on Python.
- suprjami 3y agoThis problem of skill shortcuts is not confined to programming. I work on networking. People always want to learn "packet capture analysis" because Wireshark has a cool name and looks impressive. imo there is no such skill as packet capture analysis. Once one learns the OSI model and a bunch of Ethernet and TCP/IP implementation behaviour, then what Wireshark presents becomes obvious and supported by that contextual knowledge.
- Jorengarenar 3y agoIt's kind of amazing how many university programs teach C(++) just wrong. Wrong and outdated! Apparently, in India many schools still didn't update the curriculum and teach Turbo C!
- AdamH12113 3y ago-Wdouble-promotion can be a big help on microcontrollers with 32-bit FPUs. An accidental double promotion can be the difference between a single CPU instruction and an implicit function call to a built-in software computation. Not a nice thing to have in one of your inner loops! Setting the compiler to treat floating-point literals as floats instead of doubles helps too, but I still add the trailing ‘f’ just to be on the safe side.
- camel-cdr 3y agoI also find setting -std=c11 and -fpedantic very important, as otherwise you are writing against the gnu89 and don't get warnings about extension usage.
- augustk 3y agoOr -std=c89 and -pedantic for improved portability.
- suprjami 3y agoNot quite: https://gcc.gnu.org/onlinedocs/gcc/Standards.html https://gcc.gnu.org/onlinedocs/gcc/Standards.html > The default, if no C language dialect options are given, is `-std=gnu17`.
- account42 3y agoThis depends on the compiler version. The default was stuck at gnu89/gnu++03 for a long time.
- mytailorisrich 3y agoIt's good practice to turn on all warnings but then what? If the aim is no warnings, and that can even be a hard rule, then you also want to add -Werror to treat all warnings as errors. That might sound drastic but that in fact enforces discipline and the removal of warnings and is IMHO very good practice especially if you start doing that from day one. For legacy projects this can be a goal after an comprehensive phase of warnings removal. I've worked on projects with and without "all warnings as errors" and ultimately it is well worth it.
- rwmj 3y agoYes, but don't turn it on except in developer builds. For downstream packagers it's a pain if a newer compiler adds a warning which then breaks the build.
- DyslexicAtheist 3y agoI see your point, and agree it might be painful. it depends on the promises the maintainer makes to themselves and to their users. I'd rather break the build and get immediately alerted by (hopefully moderately) upset downstream packagers than having this warning become visible in my users builds. It isn't just about getting rid of a warning, but the new compiler has changed some important logic so this warning might highlight potentially undefined behavior. Am I, the maintainer OK with that - that is the main question I believe. Might be useful to do regression with any new compiler being released especially when a product is used in safety or security critical systems.
- rwmj 3y agoThe trouble is a downstream packager might be compiling the whole distro -- 1000s of packages -- and they're not in a position to fix a new warning somewhere deep inside a program they don't know and probably don't use. They are more likely to hack the build system to add -Wno-error while cursing the upstream project.
- 3y ago
- rwmj 3y agoHere's a few more we use: -Wvla Warn about any use of stack-allocated variable length arrays. There are a couple of reasons why these are bad: without care they can cause exploits where a caller specifies a very large array which crashes the program. And they are a problem where stack space is limited (kernel code, threads on 32 bit machines). -Wframe-larger-than=5000 -Wstack-usage=10000 Prevent large stack frames. Same reasons as above. -Wshadow Prevent shadowed variables, eg. a local variable with the same name as a global. -Werror Turn warnings into errors. Only use this for developer builds though, because newer compilers introduce new warnings and that will cause problems for downstream packagers. -fno-omit-frame-pointer https://rwmj.wordpress.com/2023/02/14/frame-pointers-vs-dwarf-my-verdict/ https://rwmj.wordpress.com/2023/02/14/frame-pointers-vs-dwar... -fvisibility=hidden When building a library, make sure all symbols between compilation units but within the library are not exported. Basically reduces the load-time overhead and prevents random ELF symbol interposition. If you use this, then to export a symbol you have to use '__attribute__((__visibility__("default")))'. -fno-strict-overflow -Wno-strict-overflow (Controversially) unbreaks the C compiler by allowing signed overflows to do the obvious thing.
- DyslexicAtheist 3y ago> -fno-omit-frame-pointer agreed on 64bit. Also this advise is old it hasn't popped up out of nowhere. I still recall it being crucial back in the early 2000's to improve performance. And today it remains very valid because of 32 bit IoT systems.
- rwmj 3y agoRight, on 32 bit you do want to omit frame pointers so %ebp can be used as a general register. (Fedora is on the verge of dropping 32 bit platforms entirely.)
- pajko 3y agoFrame pointers are old-school technology for most of the platforms, even in embedded usage. The libunwind library should be used instead, with the -funwind-tables or -fasynchronous-unwind-tables compiler options and additionally -rdynamic, -fno-dwarf2-cfi-asm, -fvar-tracking-assignments.
- deleted 3y ago[deleted]
- flohofwoe 3y agoUnlike recommended in the article, I started to enable -Wsign-conversion on my own code. At first it's very annoying because it's noisy and full of false positives (where the implicit sign conversion definitely can't cause any trouble), but it's definitely a good thing for becoming aware of places where integer promotion kicks in and might potentially cause unexpected results.
- jedisct1 3y agozig cc has great defaults, which includes UB sanitizers. Quite a few projects had bugs found and fixed just by compiling them with zig cc instead of gcc or clang.
- bighoki2885000 3y ago[dead]
- tester756 3y agodont you folks believe that some of those should be ON by default?
- rwmj 3y agoChanging defaults is hard and I can understand why compiler writers would be reluctant: Many of the suggested warnings will reject valid-but-marginal code that you might not have time to rewrite (or might not be able to, eg. it's in an external library that you don't understand well). Sanitisers and static analysers very often complain about quite valid code that doesn't need to be fixed at all. Some hardening flags cause significant performance regressions. Who is to say that -g3 is the best option? It causes huge binaries to be generated which might not be useful if you have other means to debug the code or can't/don't use gdb.
- mgaunard 3y agoMost of the useful flags are either on by default or do all get enabled with simple meta-flags. It's just that some people never bother to read the docs.
- preseinger 3y agomost of the comments you make on this website are incorrect, this one included do you maybe want to consider taking a step back and re-evaluating your opinions?
- mgaunard 3y agoDid they actually fix abort on error for ubsan? I've always been setting a breakpoint of ~Diag instead since it doesn't work.
- sailorganymede 3y ago-g is my favourite flag. You'll be surprised how many people just don't use the debugger when they're doing C.
- account42 3y agoI'm confused, can't you use printf without -g?
- beeforpork 3y agoI think -Wno-sign-conversion is a bad idea if you like -Wconversion. It's either with or without conversion warnings, in my opinion, because while you do not lose bits when assigning an unsigned to an int (or vice versa), you do get a misinterpretation of the sign bit and thus a change of the conceptional value the bits represent. It's just highly annoying in C that no-one cares, because C integer typing is so lax by default.
- PhilipRoman 3y agoReally wish gcc had a -std flag for "POSIX but no GNU extensions". Currently you're forced to choose between -std=cXX for the pure C standard or -std=gnuXX for C + POSIX + GNU extensions.
- JoshTriplett 3y agoYou can use POSIX functions in -std=c17 or similar. For instance: #define _POSIX_C_SOURCE 200809L #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *x = strdup("hello world"); printf("%s\n", x); free(x); return 0; }
- account42 3y agoExactly, these are libray extensions so they are controlled via defines and not (directly) via compiler flags. Which ones there are (and what they do) depend on the standard C library and not the compiler. For glibc: https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_node/libc_13.html https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_node/li...
- nwellnhof 3y agoAnother great UBSan feature is -fsanitize=integer which detects truncation and sign changes in implicit casts. But if you start using it, you'll realize that explicit casts enforced by -Wconversion only hide errors. You really have to remove as many explicit casts as possible to detect unwanted truncation. After testing and fuzzing with -fsanitize=integer for a while, I came to the conclusion that implicit casts are a feature and C even has an advantage there compared to other languages which require explicit casts. To test for unwanted truncation, you really need two different casting operations. One which silently truncates in the rare cases where you really need it and another one which warns about truncation in test builds. So my recommendation is: Remove all explicit casts and warnings like -Wconversion. Test with -fsanitize=integer. If UBSan detects truncation, you can often adjust some types so that no truncation happens. Only use explicit casts if you must convert between signed and unsigned chars for example.
- Gibbon1 3y ago> you'll realize that explicit casts enforced by -Wconversion only hide errors I find I'm increasingly annoyed with the advice to 'just add a cast' to fix conversion issues. And safely casting between signed and unsigned is something that should have been added to C about 40 years ago.
- pixelbeat__ 3y agoThe gnulib manywarnings module is useful to add as many warnings as appropriate in a portable manner https://www.gnu.org/software/gnulib/manual/html_node/manywarnings.html https://www.gnu.org/software/gnulib/manual/html_node/manywar... That's used in dev mode for various projects like GNU coreutils etc. When distros etc. are building though these warnings are not used. It's worth stating as I've seen this issue many times, that -Werror at least should not be used by default for third parties building your code
- ranger207 3y ago"Having strong opinions on which compiler flags to use" seems like it'd be a bit miserable. Flags should be for either unusual situations where you want to do something differently, or for situations where you're required to make a choice. If these flags are useful >90% of the time, why aren't they default?
- bighoki2885000 3y ago[dead]
- maarten_db 3y ago-Wstrict-prototypes
- suprjami 3y agoI also like this one and `-Wmissing-prototypes`. https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wstrict-prototypes https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#inde... https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmissing-prototypes https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#inde...
- calandoa 3y ago[dead]