Chapter 10-02

Source: Internet
Author: User

Please indicate the Source:http://blog.csdn.net/gaoxiangnumber1
Welcome to my Github:https://github.com/gaoxiangnumber1
10.4 Rules for the use of header documents in engineering projects
10.4. The harm of 1 header files
? I think the harm of the head file is mainly reflected in the following aspects:
1. transitivity.
The header file can contain additional header files. A simple # include extension has more than 20,000 lines of code, which causes the compilation to be slow; on the other hand, any change to a bit of a header file will require recompiling all the source files that directly or indirectly contain it. Because the build tool cannot effectively determine whether this change affects program semantics, it is only possible to recompile the affected source files all over again in a conservative way.
2. Sequential nature.
A source file can contain multiple headers. If the content of the header file is not organized properly, it will cause the semantics of the program to be related to the order in which the file is contained, or whether it contains a header file about 66. The usual practice is to divide the head file into several categories of 67, and then include the header file 68 in order, with the same class header file sorted alphabetically by file name. On the one hand, the source code is relatively neat; on the other hand, if two people change the source at the same time, each want to include a header file, then the likelihood of conflict is less. Avoid adding a new header file at the end of the # include list every time, so that the code dependencies are not managed quickly.

3. Differences.
Differences in content result in inconsistent header files seen by different source files, and time differences cause the header files to not match the contents of the library files. As §12.7 mentions, different compilation options cause Visual C + + std::string to differ in size. This means that the contents of the header file will change after preprocessing, and if the macro definition options at compile time for two source files are inconsistent, the binary code may not be compatible. This means that the entire program should use a unified compilation option of 69. If the program used a third-party static library or dynamic library, in addition to the header files and library files, we also have to compile the library compile options, in order to use the library safely and without error. If the program uses two libraries, but their compilation options conflict, then the trouble is big, later on the library file organization when the problem and time differences.

? Modern programming languages are better modular. There are two main types of modular approaches:
1. For an interpreted language, import will parse the source file of the corresponding module (parse) Once (it is no longer simple to include the source file).
2. For the compiled language, the compiled target file (for example, Java. class file) contains sufficient metadata, the import only need to read the contents of the target file, do not need to read the source file.
Both of these practices avoid the issue of inconsistent declarations and definitions, because declarations and definitions are integral in these languages. At the same time, this import does not introduce unwanted names, greatly simplifying the burden of name lookup (whether it is the human brain or the compiler), and do not worry about the different order of import causes the code function changes.
10.4. Usage rules for 2 header files
? The idea of a header file in the C + + programming specification is summarized as follows
1. "Minimize compilation dependencies between files. "[EC3, clause 31]
2. "Minimize the dependencies between definitions. Avoid cyclic dependencies. "[CCS, clause 22]
3. "Let the class name, header file name, source file name directly related." "70 This facilitates the positioning of the source code. Muduo follows this principle, for example TcpClient class header file is TcpClient.h, and its member functions are defined in tcpclient.cc.

4. "Make the header file self-sufficient. [CCS, clause 23] For example, to use Muduo's tcpserver, you can include TcpServer.h directly. In order to verify TcpServer.h's self-sufficiency (self-contained), tcpserver.cc the first included header file is it.
5. "Always write internal #include guard (sheath) inside the header file, do not write the external sheath in the source file. [CCS, Clause 24] This is because the current preprocessing is particularly optimized for this common practice, and the GNU CPP does not even read the file when it is the second # # # file, but skips directly.
6. The name of the macro that #include guard should contain the full path of the file (from the version Manager's perspective), plus the project name if necessary (if each project has its own code warehouse).
7. If you write a library, the exposed header file should express the interface of the module and, if necessary, put the implementation details into the internal header file. The Muduo header file satisfies this rule (§6.3).
? Describes a technique for finding a header file that contains a path. For example, there is a program that only contains, but can use std::string, I want to know how to be introduced. The idea is to create a string file in the current directory and then make a compilation error, as follows:

10.5 Organization principle of library document in project
? Consider a company that has a team development company's public C + + network library net; There is also a team that develops a set of message middleware and provides a client library Hub,hub is Net-based; another team of companies developed a storage system and provided a client library cab, The CAB is also built on net. A service-side program developed within the company may use one or more of these libraries, and this section discusses how to organize libraries and applications developed by different teams.
? Talk about the basic topic: dependency Management.
? Let's say you're in charge of a program app, and after testing, App 1.0 runs on the go and everything goes well. App 1.0 uses the network library (NET 1.0) and the client library of the message Middleware (Hub 1.0), and hub1.0 itself uses NET 1.0, as shown in dependency 10-3.

Although the QA staff sign-off the app 1.0 before the release, we should assume that they sign-off the bundle of App 1.0 and all the libraries it relies on. Because the app behaves in relation to the library it uses, if you change any of the libraries, the app's behavior can change (although the app's source code and executable file do not move one byte), it may be inconsistent with the "app 1.0" behavior that was passed at the time of the test.
In 1th. 7.2, "COM testability analysis" in software testing practice, Zhou Weiming said that COM "violates the fundamentals of software Design" on the grounds that we assume that a software contains n different COM components, and that each component can be replaced by COM's design idea. Assume that each component has several different versions, which are recorded as M1, M2, ... MN A different version, then the composition of all components of the entire software has a m1xm2x...xmn, equal to the software is a common m1xm2x...xmn binary version. If you want to do the testing well, all of these combinations need to be tested, otherwise it's hard to guarantee that the combination you haven't tested will not be a problem.
? This theoretically shows that the change itself or the library it relies on should be re-tested, otherwise the version that was passed by the test and the version that was actually running is two things at all. If there is a problem, the responsibility is difficult to clarify.
? This problem also exists for languages other than C + +, and any language that can replace the library after compilation needs to consider a similar problem. For scripting languages, in addition to libraries, the version of the Interpreter (python2.5/2.6/2.7) also affects the behavior of the program, so there are tools such as Python virtual env and Ruby rbenv that allow a single machine to install multiple interpreter versions at the same time. The Java program behaves in addition to those jar files in class path, as well as the JVM version, and usually we cannot upgrade a large version of the JVM (from 1.5 to 1.6) without sufficient testing.
? In addition to the library and the runtime environment, there is a dependency on external processes, such as the application relies on some data sources (processes running on other machines), at run time through some kind of network protocol from these data sources periodically or irregularly read data. The data source may be upgraded, its behavior may change, and how this dependency is managed is beyond the scope of this section.
Back to C + +, first talk about compatibility between compiler versions. As of G++4.4,linux there are currently four incompatible ABI version 75, the compiled libraries are not common:

Versions prior to 1.GCC 3.0, e.g. 2.95.3
2.GCC 3.0/3.1
3.GCC 3.2/3.3
4.GCC 3.4~4.4
? This has little effect because it is estimated that no one is using g++3.x to compile new code.
? You also need to consider the version of the C + + standard library (libstdc++) and the C standard library (GLIBC). The version of the C + + standard library is directly associated with the C + + compiler. The version of the C standard library is directly related to the version of the Linux operating system.

? Typically no one upgrades glibc alone, as this means that all code for the user's state needs to be recompiled. For the sake of safety, it is generally advisable to compile the code with the GCC version that comes with the Linux distribution. Because this version of GCC is the most supported compiler version of the Linux distribution.
? According to the above analysis, once the version of the operating system is selected, the other three versions of things are determined. For the time being, the Linux operating system version, the libstdc++ version, the glibc version of the machine running app1.0 are unified, and the code for C + + applications and libraries is compiled with the native g++ of the operating system.
In this way, we can discuss the organization of applications and libraries in cases where the C + + compiler version, the C + + standard library version, and the C standard library version are fixed. This discussion is about the libraries implemented within the company, not the operating system's own compiled libraries (LIBZ, Libssl, Libcurl, and so on). These libraries can be deployed uniformly through the package management mechanism of the operating system to ensure that each machine has the same environment.
? The shared library of Linux is much more useful than the Windows dynamic-link library in C + + programming and is basically transparent to the application, no different from using static libraries. Mainly reflected in:
1. Consistent memory management. The Linux dynamic library shares the same heap as the application, so the memory allocated by the dynamic library can be given to the application to release 82, or vice versa.
2. Consistent initialization. Static objects in a dynamic library (global objects, namespace objects, and so on) are initialized in the same way as static objects elsewhere in the program, without specifically distinguishing the object's location.
3. You can safely use class, STL, Boost (if the version is the same) in the interface of the dynamic library.
4. There is no dllimport/dllexport of the burden. Direct include header files are available.
The problem with 5.DLL Hell83 84 is small because Linux allows multiple versions of a dynamic library to coexist, and each symbol can have multiple versions of 85.



? DLL hell refers to the update of a common DLL when new software is installed, which destroys the functionality of other existing software. For example, installing XYZ 1.0 will upgrade the Net Library to version 1.1, overwriting the original app 1.0 and Hub 1.0-dependent NET 1.0, which is potentially risky (figure 10-4).

? A C + + library is published in three ways: a dynamic library (. So), a static library (. A), a source code library (. cc). Table 10-2 summarizes some of the basic features.

In this section, the dynamic library includes only the general usage of the link dynamic Library at compile time, not including the usage of the runtime dynamic Loading (Dlopen ()).
As the author of the application, if you want to run this program on multiple Linux machines, we'll first deploy it to those machines.
1. If the program relies only on libraries provided by the operating system itself (including the third party libraries that can be installed through the package management software), it can be run as long as the executable file is copied to the target machine. This is one of the outstanding advantages of static library and source repository in distributed environment.
2. If you rely on dynamic libraries that are implemented within your company, these libraries must be deployed to these machines beforehand (or at the same time) for the application to function properly. The challenge: Who does the work of deploying a dynamic library (the author of the library or the author of the application) do? Another question is, if the author of the dynamic library fixes the bug, can he update the library on all of the machines on his own?
? We think that the author of the library can independently deploy and update the dynamic library and affect the application 88 that uses the library. Otherwise, if each program has its own dynamic libraries and applications packaged together for publishing, the library's authors are not responsible for the library updates, then this and the use of static libraries is no different, and not as direct static links.

? Either way, we have to ensure the independence of the application, that is, multiple large versions of the dynamic library can coexist. For example, after deploying App 1.0 and XYZ 1.0, the dependency 10-5 is shown.

According to traditional view, dynamic cubby Static library saves disk space and memory space 89, and has the ability of dynamic update (can hot fix bug90), it seems that dynamic library should be the current preferred. But it is this dynamic update 91 capability that makes the dynamic library a hot potato.



10.5.1 Dynamic Library is harmful
? Jeffrey Richter93 on the nature of the dynamic library: Once you replace the dynamic library used by an application, the program that was previously working properly will no longer be the same as the original build and test code. The result is that the behavior of the program becomes unpredictable. How to fix bugs and add feature while still ensuring that existing applications are not corrupted? Conclusion: This is not possible.

The author of the library certainly does not want the update to deploy a bug fix, which woke up in the morning of Monday by the phone of the maintainer of the application, saying that the program could not be started (the new library broke binary compatibility) or that it did not meet the expected behavior.
? Is it possible to fully test all affected applications before releasing the bug fix for the dynamic library? This encounters a dilemma:
1. The use of a dynamic library is narrow, only two or three programs used it, the cost of testing is low, it is not obvious as the advantages of dynamic library.
2. The use of a dynamic library is wide, dozens of programs use it, the "advantage" of the dynamic library is obvious, and the cost of testing and updating is correspondingly high (perhaps high to offset its "advantage").
? One way to do this is to publish the update of the dynamic library to the QA environment, and then publish it to the production environment for a period of time, and there is also a problem: when testing the next version of App 1.1, will the dynamic library version of the QA environment be used for the dynamic library version of the production environment? If the program changes after the test is compiled, is it a waste of QA?
? In short, once a dynamic library can be updated frequently, there is no perfect way to use a dynamic library. Before you decide to use a dynamic library, you should at least familiarize yourself with its various pitfalls. The resources are as follows:
? http://harmful.cat-v.org/software/dynamic-linking/
? "A Quick tour of compiling, linking, Loading, and handling Libraries on Unix" (http://ref.web.cern.ch/ref/CERN/CNL/2001/0 03/shared-lib/pr/).
"How to write Shared Libraries" (http://www.akkadia.org/drepper/dsohowto.pdf).
? "Good practices in Library Design, implementation, and Maintenance" (http://www.akkadia.org/drepper/goodprac-tice.pdf).
? Solaris Linker and Libraries Guide (http://docs.ora-cle.com/cd/E19963-01/html/819-0690/).
? "Shared Libraries in SunOS" (http://www.cs.cornell.edu/courses/cs414/2004fa/sharedlib.pdf).
10.5.2 Static library, not anywhere.
There are several advantages to a static library compared to a dynamic library (http://en.wikipedia.org/wiki/Static_library):
1. Dependency management is determined at compile time, without worrying about the future libraries it will use. Similarly, debugging a core dump does not result in the failure of the debug symbol when the library update is in progress.
2. It may run faster because there is no PLT (Procedure lookup table) and the function call is less expensive.
3. Easy to publish, just copy a single executable file to the template machine.
A disadvantage of a static library is that links are slower than dynamic libraries.
? The static library author compiles the source file into a. A library file, which is packaged and released together with the header file. The application author compiles its own code with the library's header file and links to the. A library file to get the executable file. There is a compile time difference: Compiling the library file is earlier than compiling the executable, which may cause the header file to be seen when compiling the application to be different from compiling the static library.
For example, it uses boost 1.34 when compiling net 1.1, but it uses boost 1.40 when compiling XYZ application, as shown in Figure 10-6. This inconsistency can cause a compilation error or cause a run error. For example, net libraries provide callbacks with boost::function, but boost 1.36 removes a template type parameter, which causes XYZ 1.0 to be incompatible with the net1.1 with boost 1.40.

? This means that the application must use the same development environment (the lower library, compiler version, compiler option) when using the static library. But what if the dependencies of two static libraries are conflicting?
The static library puts the version dependencies between libraries completely at the compile time, which is easier than the dynamic library, but it's still not easy. Several situations that may be encountered:
1. Forcing the upgrade to a higher version. Let's say that the app 1.0 depends on Net 1.0 and Hub 1.0, everything is OK, and 10-7 is shown in the image on the left. When we developed app 1.1, we used the Net 1.1 feature. However, the Hub 1.0 still relies on the author of the Net 1.0,hub library for the time being to upgrade to net 1.1. If you are not careful, it will cause the Hub 1.0 link to the net 1.1,10-7 to the right image. This is different from compiling the Hub 1.0 environment, and the Hub 1.0 behavior is no longer fully tested.

2. Repeat the link. If Makefile is poorly written, it is possible that the Hub 1.0 continues to link to Net 1.0, while the application is linked to net 1.1, as shown in the 10-8 left image. At this point, if the Net library has internal linkage static variables, it can cause strange behavior, because the same variable now has two entities, violating the ODR. A concrete example of the cloud-wind blog 97.


3. Version conflicts. Let's say the app is upgraded to version 1.2 and wants to add a library cab1.0, but Cab 1.0 relies on the net 1.2,10-8 to the right. Our problem is that if you use NET 1.1, you do not meet the requirements of CAB 1.0, and if you use NET 1.2, you do not meet the requirements of hub 1.1. What should I do then?
? If an application uses three or four static libraries within a company (Figure 10-9), it can be a little tricky to reconcile the versions between libraries, and upgrading any library individually could undermine its original dependencies.

The evolution of static libraries is also troublesome. So far we think the company has no historical baggage, all the machines are bought around 2009, running is Ubuntu8.04 LTS, the software version is g++4.2, glibc 2.7, boost 1.34, etc., C + + programs and libraries are also in this unified environment developed. Now in 2012 years, the online server has been in service for 3 years, into the replacement cycle. The newly purchased machine intends to upgrade to Ubuntu 10.04 LTS. This also upgrades the kernel, gcc 4.4, glibc 2.11, boost 1.40.
? This requires the author of the Static library to recompile and publish the new library file for the new system. To avoid confusion, we had to add a suffix to the library to identify the environment and dependencies. Assuming that there are currently active libraries such as NET 1.0, NET 1.1, Net 1.2, Hub 1.0, Hub 1.1, and CAB 1.0, you need to publish multiple versions of the static library:
Net1.0_boost1.34_gcc42
Net1.0_boost1.40_gcc44
Net1.1_boost1.34_gcc42
Net1.1_boost1.40_gcc44
Net1.2_boost1.34_gcc42
Net1.2_boost1.40_gcc44
Hub1.0_net1.0_boost1.34_gcc42
Hub1.0_net1.0_boost1.40_gcc44
Hub1.1_net1.1_boost1.34_gcc42
Hub1.1_net1.1_boost1.40_gcc44
Cab1.0_net1.2_boost1.34_gcc42
Cab1.0_net1.2_boost1.40_gcc44
? This combination of explosive growth is a surprise because any one of the underlying libraries adds a Variant (variant), and all the high-level libraries that rely on it will compile a version for it.
To get rid of this dilemma, the solution is to use the source repository, where each application compiles the required libraries from scratch, minimizing the time difference.
10.5.3 source code compilation is kingly
? Each application chooses which library to use and compiles itself into a single executable file. Avoid the time difference between the header file and the library file, ensuring that the source files for the entire project are compiled with the same compilation options, and don't worry about the library version. The disadvantage is that the compilation time is long because the compilation tasks of each library are passed from the author of the library file to the author of each application.
? It is best to work with the source version tool so that the application can only specify which library to use, and the build tool automatically helps us check out the source of the Out library. So the author of the library only need to maintain a few branch, publish the library without the need to package the head file and library files for download, as long as the push to a specific branch on the line. And the build tool is best able to parse the library's makefile (or equivalent build script), automatically helping us to solve the library's transitive dependency, as Apache Ivy can do.
Summarize
? Because the header file of C + + is detached from the source file and there is not enough metadata in the destination file for the compiler to use, both the library file and the header file must be provided. That is to say, if you want to use a compiled C + + library (whether it is a static library or a dynamic library), we need two things, one is the header file (. h), the other is the library file (. A or. so), and there is a possibility that these two things will not match. This is the root cause of the simple and vulnerable module mechanism of C + +.
Pending resolution
? DLL Hell Problems
? compiler's Abi

? extern "C"
? One-time definition principle (ODR)
In the header file, write the internal #include guard (sheath), do not write the external jacket in the source file???
Please indicate the Source:http://blog.csdn.net/gaoxiangnumber1
Welcome to my Github:https://github.com/gaoxiangnumber1

Chapter 10-02

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.