Hacker News new | ask | show | jobs
by bluGill 2760 days ago
it is also less bugprone in the real world. There are cases where it doesn't work, but they amount to stupid things that nobody does outside of contrived examples.

I switched our codebase after finding several variations of #ifdef message_h #define massage_h That potential bug existed in our code base for years (I checked history)

2 comments

Fwiw Google solves this problem by having tooling generate the file template.

In other words, my vimrc pulls in a global vimrc that, when I open a new .cc file, it starts as a stub that has the correct ifdefs and some common imports (flags iirc). This, combined with a lint/presubmit that prevents submission of files missing the correct defs makes this a nonissue in practice.

The worst thing that happens due to this "potential bug" is that someone introduces a double inclusion of that header, which fails to be suppressed and the build blows up in their face due to duplicate definitions.

The error could be diagnosed by the compiler---submit a patch to gcc!

That is to say, if the following pattern occurs around the content of the file:

   #ifndef <whatever0>
   #define <whatever1>

   #endif
the compiler can validate that <whatever0> and <whatever1> are the same symbol, and emit a warning if they aren't.

Note that GCC already looks for this pattern and optimizes it! That has been implemented for ages; probably twenty years if not more. See here:

https://gcc.gnu.org/onlinedocs/cpp/Once-Only-Headers.html

That optimization must have a check in place that it's the same symbol in both places. And so that piece of code which checks can probably be augmented to emit a warning fairly easily.

A sophisticated version of the warning would only kick in if the symbols appear to be similar (e.g. close by Levenschtein distance) so that one of them is plausibly a typo for the other.

Another solution is to have a commit hook which looks for such a problem: it enforces the include guard on headers, and checks that the symbols match.

clang actually does have the warning you want gcc to have - this is how I found our instances of it.

What none of the above can do is two different projects have MESSAGE_H headers that are different can fully compatible to include both. #pragma once handles this correctly.

The clash between two different MESSAGE_H can be rendered vanishingly unlikely by having a convention of adding some random digits.

I adopted the following pattern some twenty years ago of affixing a random 32 bit number in hex:

   #ifndef MESSAGE_H_3DF0_9A73
   #define MESSAGE_H_3DF0_9A73

   #endif
If only the filesystem would assign some sort of unique, 32- to 64-bit identifier to files that a compiler could use to distinguish one header from another. We could call them inode numbers. Hmm. No, I'm sure no one has ever thought of the problem of identifying unique files before.[0][1]

I guess instead we must embed GUIDs in every file to keep track of uniqueness.

[0]: https://stackoverflow.com/a/13172784/218830

[1]: https://stackoverflow.com/a/1866547/218830

Copies of a file have different inode numbers.
I can agree with this statement of fact. I'm missing the part where it's relevant to the conversation or informs some conclusion.