About the protected header file

I am reading a book about Applied C ++.

Enabling security devices will prevent the inclusion of a header file than once during compilation of the source file. Your character names must be unique, and we recommend that you select a name based on the file name. For example, our cache.h file contains this: guard.

#ifndef _cache_h_ #define _cache_h_ ... #endif // _cache_h_ 

Lakos describes the use of redundant included guards to speed up compilation. See [Lakos96]. For large projects, it takes time to open each file, only to find that the inclusion protection symbol is already (i.e. the file is already included). The effect on compilation time can be dramatic, and Lakos shows a possible 20x increase in compilation time when only guards are standard b.

[Lakos96]: Software development for LargeScale C ++.

I do not have a Lakos96 reference for concept designation, so ask for help here.

My questions on the text above

  • What does the author mean: “For large projects, it takes time to open each file, only to find that the inclusion protection symbol is already defined”?

  • What is meant by the term “when safety devices are normally turned on”?

Thanks for your time and help.

+6
source share
6 answers

From C ++ Coding Standards (Sutter, Alexandrescu)

Many modern C ++ compilers automatically recognize header protection (see Section 24) and do not even have to open the same header twice. Some also offer precompiled headers that help ensure that frequently used, rarely modified headers are often not parsed.

So, I would consider these suggestions obsolete (if you are not already using some very obsolete compiler).

Regarding your questions:

  • this means: opening a file that is not needed (since it is already included, which you recognize because the inclusion protector is already defined) is expensive; and this can be a problem if you do it many times (what can happen if there are hundreds of files in your project).
  • as opposed to using backups with redundancy.

What is a backup compiler?

The naive compiler will reload the file every time it is included. to avoid this, add RedundantIncludeGuards around include: header.h

  #ifndef HEADER_H_ #define HEADER_H_ // declarations #endif 

foo.c

  #ifndef HEADER_H_ #include "header.h" #endif 

read here . Your link states that by doing this, you can be 20% faster at compile time than if foo.c only executed

  #include "header.h" 
+8
source

I don’t know what Lakos96 says, but I’ll guess anyway ...

The standard includes protection:

foo.h

 #ifndef FOO_H_INCLUDED #define FOO_H_INCLUDED .... #endif 

In abundance, protection is enabled using a macro when a file is included:

bar.c

 #ifndef FOO_H_INCLUDED #include "foo.h" #endif 

Thus, the second time the foo.h file is included, the compiler does not even look for it on disk. Therefore, acceleration: imagine a large project, one single compilation unit can include foo.h 100 times, but only the first will be processed. The remaining 99 times will search, open, mark, drop the preliminary compiler and close.

But note that this was in 1996. Today, GCC, to give a well-known example, has certain optimizations that recognize the inclusion protection pattern and makes redundant inclusion protection, well ... redundant.

+6
source

The book of Lakos is out of date. This may have been true once, but you should put the time on your car. Many people now disagree with him, for example. http://www.allankelly.net/static/writing/overload/IncludeFiles/AnExchangeWithHerbSutter.pdf or http://c2.com/cgi/wiki?RedundantIncludeGuards or http://gamearchitect.net/Articles/ExperimentsWithIncludes.html

Herb Sutter, a C ++ guru and current chair of the ISO C ++ standards committee, claims against outside guards include:

"By the way, I strongly disagree with the external Lakos guards for two reasons:

  • Most compilers have no benefit. I admit that I didn’t take measurements, as it seems that Lakos then did, but as far as I know that compilers already have smart people to avoid re-assembly time to re-read the overhead - even MSVC does this optimization (although it requires you to say "#pragma once"), and it is the weakest compiler in many ways.

  • External ones include encapsulation-violating fences because they require many / all callers to know about the internal elements of the header, in particular the special name #define used as a protector. They are also fragile - what if you're wrong? what if the name changes? "

+5
source

A large project can have many headers - perhaps 100 or even 1000 files. In the normal case, when guards are included in each header, the compiler should check (but see below) the contents of the file to see if it is included.

These defenders inside the header are standard.

Lakos recommends (for large projects) to place guards in the #include directive, that is, the header will not even need to be opened if it is already on.

However, as far as I know, all modern C ++ compilers support the #pragma once , which in combination with precompiled headers means that the problem is no longer a problem in most cases.

+1
source

I think this refers to replication of the include security object outside the header file, for example.

 #ifndef _cache_h_ #include <cache.h> #endif 

However, if you do, you will have to think that header protectors sometimes change inside the file. And you, of course, will not see a 20-fold improvement in a modern system — if all your files are not on a very remote network drive, perhaps — but then you will have a much better improvement from copying project files to a local drive!

A similar question was repeated regarding “including redundant files” (referring to the inclusion of header files several times), and I built a small system with 30 source files that included <iostream> “unnecessarily”, and the total compilation time difference was 0.3 % between inclusion and absence of <iostream> . I believe that this conclusion shows an improvement in GCC that "will automatically recognize files that do not produce anything outside the included guards."

0
source
  • in large projects with a large number of people, for example, there may be one module that deals with time conversion, and the author could use TIME as a defender. Then you will have another one concerning the exact time, and an author who is not aware of the first can choose TIME too. Now you have a conflict. If they used TIME_TRANSFORMATION and PRECISE_TIMING_MODULE , they will be fine

  • I do not know. I would suggest that this means that "when you do this every time, sequentially, it becomes your coding standard."

0
source

Source: https://habr.com/ru/post/950057/


All Articles