Hacker News new | ask | show | jobs
by tenfingers 4478 days ago
"-Winit-self" actually disables the common "var x = x" idiom which is used to silence "uninitialized variable" warnings.

Personally I consider "-Werror" stupid. Warnings are designed to help and be reviewed, but aiming at "100% warning free" code should not be an "aim". For instance, I'd rather have "unitialized warnings" than use "i = i", which you know, might actually be correct code if "i" was available in scope and you want an additional copy that you can modify (nester for loops come to mind).

I sometimes leave warnings when silencing them "uglifies" the code.

"-fvisibility=hidden" is not so easy to leave on all the time when building software build by others. What I use is mostly "-fvisibility-inlines-hidden" in C++ code, even when building OSS projects, for which I never had a problem so far (in c++ inlines _are_ expected to have hidden visibility).

I also use "-march=native -flto=jobserver" and "-fwhole-program" (when linking) when I'm targetting my own hardware.

I also noticed that gcc now supports "-Og" to build optimized programs without impact on debugging, for which I had a very long command line before. "-Og -g3" gives pretty decent performance and optimal debugging, which is ideal for beta-testing programs.

gcc supports a pretty infinite list of command line switches. Actually, if you know what you are doing, you can optimize a program so well it's pretty much impossible to beat even by hand-crafting assembly. I know I tried several times, before realizing I could move a function to a separate object and supply a different set of optimization flags tuned just for that function.

For instance, "-Ofast" is actually safe most of the time for system utilities (and most other OSS software), and gives quite a boost for programs working with floats (most image-resizing loops and the like). Very few programs actually rely on exact IEEE arithmetic. Though I never use it, since finding issues might be _very_ hard.

3 comments

> "-Winit-self" actually disables the common "var x = x" idiom which is used to silence "uninitialized variable" warnings.

so now we have a flag that disables a hack in code that is used to disable a warning caused by another flag. This is about as ridiculous to my (untrained in C) mind as it is to have -Wall not in-fact turn on all warnings.

The number of warnings that GCC can generate can cover some very speculative grounds, which are sometimes legitimate code. In fact many C idioms that were considered commonplace are now "warnings" because of the subtle semantics.

Take assignment/evaluation in a condition:

  if(a = [expr])
was not so frowned upon before, because it was sort of implicit that "a" was also needed in the nested block that followed. Now it's a warning without a double parenthesis, because it's also common the typo of using = instead of ==.

The list goes on and on. In fact, the level of diagnostics that you get in C is pretty bit, and probably one of the best in class compared to any other language thanks to the maturity of the toolchain.

If you're using var x = x; then stop. The compiler is able to validate that assignment to variables are never used using data flow analysis, so always initializing has no cost once optimizations are turned on. Beside, even if it was not optimized away, until a profiler actualy shows that a variable initialization is your bottleneck, it's a waste of time and will make code refactoring harder and cuase bug down the line. Maybe not in this function, maybe not by you, but someone will add a new conditional branch somewhere where your variable won't be initialized.

As for the optimization, I just tested on my machine:

   int main(int argc, char** argv)
   {
      int x = 0;

      switch (argc)
      {
         case 0:
            x = 1;
            break;
         case 1:
            x = 5;
            break;
         case 2:
            x = 7;
            break;
         default:
            x = 9;
            break;
      }

      return x;
   }

   gcc -O3 -o opt-assign opt-assign.c

   (gdb) disassemble main
Showed that x is never assigned zero.
I think you misunderstood the point. The discussion var x = x has nothing to do about performance.
-Werror is debatable. On a controlled build environment (with fixed GCC version and fixed distribution), I am convinced this is the way to go. After careful reviews, -Wno-xxx switches can be added on demand (such as -Wno-overlength-strings, haha) to limit annoying/irrelevant messages, but experience shows that having thousands of warnings in logs lead to ignore issues (this is especially true when the codebase is huge)
Except one case (gcc 2.9x), I stopped using a fixed version of a compiler a long time ago, nowdays I only use a fixed build host when needed. -Wall -Wextra -Werror will magically make your build fail because of a new warning which wasn't caught before, or a system library update, or others.

In my mind it's way better to just build your software with -Wall/others and implicitly review all warnings before pushing changed files to a common repository (which is kind of obvious, since when you are developing you also are looking the build logs).

For instance, -Wunused-args is helpful, but for a provisional API that's going to stay in the repository for a couple of weeks the warning is useless. Some people would go on and add useless code to silence the warning, though I will just commit the code.

I never had in my career large projects with more than a handful of warnings anyway. The kind of person that would use -Werror, in reality would go perfectly fine without.

> The kind of person that would use -Werror, in reality would go perfectly fine without.

Eliminating warnings can often be a hassle for no short-term benefit, and there's a decent number of people who agree that zero warnings is useful but don't actually get around to sticking to that if the compiler doesn't force them to.

The bigger benefit is when working with people that will just ignore warnings completely if you let them.