foreword
For C/C++ learners, we often hear C/C++ standard libraries, and we often use them, but we often only include header files when we use them, and then use them. We have never seriously studied them The C/C++ standard library, and the C/C++ header file only has declarations and no specific implementation of the declared content. Why can we use the library only by including the header files? In this article, let's discuss it together.
Static library and dynamic library
1. What is a library
To put it simply: Libraries are retargetable binary files that can be linked with other retargetable binary files to form executable programs when linking.
Generally speaking, libraries are divided into static libraries and dynamic libraries , and they have different suffixes to distinguish them.
System platform | static library | dynamic library |
---|---|---|
Windows | .lib | .dll |
Linux | .a | .so |
In addition, for C/C++, the name of the library also has standard requirements, such as Linux
the following : the general requirement is lib + 库的真实名称 +(版本号)+ .so /.a + (版本号)
that the version number can be omitted.
For example, these two standard libraries:
libstdc++.so.6 real name is c++
libc-2.17.so real name is c
The relationship between header files and libraries
- The header file provides the method description, and the library provides the implementation of the method. There is a corresponding relationship between the header and the library, and they are to be used together
- The header file is introduced in the preprocessing stage, and the essence of the link when the program is linked is actually the link library!
With the above basic knowledge, we can go to see the library. Linux
The system has pre-installed C&C++ header files and library files for us during installation.
For C/C++ header files, our header files are Linux
generally stored under the directory/usr/include
For C/C++ library files, it is generally in /usr/lib64
and /lib64
inside , /lib64 provides library files such as so or a required by root and the kernel, and /usr/lib64 can be used by ordinary users.
Here we can also understand some phenomena:
-
When we use a compiler like vs2019, we need to download and install the development environment. What is being downloaded?
The answer is: install the compiler software, and install the libraries and header files for the language to be developed. -
When we use the compiler, there will be an automatic syntax reminder function, but we need to include the header file first, why then?
The answer is: Grammar reminder is essentially a compiler or editor, which will automatically search the content entered by the user in the included header files. The automatic reminder function depends on the header files! -
When we write code, how does our environment know where there are syntax errors in our code and where there are problems defining variables? The answer is: don’t
underestimate the compiler, the compiler has a command line mode, and others In the automated mode, the editor or the integrated development environment can continuously help us call the compiler to check the syntax in the background without generating an executable file, so as to achieve the effect of syntax checking.
2. How to make a library
The use of libraries can improve our development efficiency, so let's make a library!
1. Static library
Static library: The program links the code of the library into the executable file when compiling and linking. When the program is running, the static library will no longer be needed. Of course, this will also cause the executable program we compile to become larger.
Take a look at the following piece of code to demonstrate the library:
head File:
Source File:
Main program:
File directory structure:
It can be seen that we put the header file and implementation file of the library in mylib
the folder, and main.c
put in otherPerson
it. At this time, mian.c
it is not with the header file and implementation file of the library, and an error will be reported when compiling.
It reminds us that we cannot find the header file. Even if we move the header file, there will be a link error. If we don’t want to give the source code otherPerson
, but we want main.c to be able to compile and form an executable program, we need to edit our library The implementation of the file is compiled but does not produce the final executable program.
Then we copy our header files and redirectable binary files into otherPerson
it
and then compile and link, and we form an executable programtest
Run test
, the program executes successfully
The whole process above is the basic process for us to make a static library. Of course, this kind of production is still flawed. When our project file is too large, we have to give a file more than a dozen such files, and the files are too .c
scattered .o
. It is not conducive to management, so we need to pack multiple such .o
files into a package. We give this package directly to others, and they can use it directly.
The packaged command is: ar -rc
command
ar
Commands are used to create or modify backup files, or to extract files from backup files. Many files can be combined to form a single backup file. In the backup file, all member files retain their original attributes and permissions.
r
: If therexxx.a
is no module in the packaged library, then the module will be added to the end of the library, and if there is, it will be replaced (the location is still the original location). : Create a backup file.xxx.o
xxx.o
c
So we try to package the original .o
files, but it should be noted that the packaged library must follow the naming convention of the library.
At this point, there is a static library in our current directory. When we delete the static library, the executable program we generated with the static library can still run normally. This is the characteristic of the static library! ! !
2. The use of static libraries
specify the path
When we actually use the library, we usually put the header file in one directory and the library in another file, which is convenient for us to classify and manage. We also follow this standardized approach to organize our directory structure.
Our libmymath.a
static library is not a standard library of C, so gcc
we will not link the static library we wrote ourselves when compiling, so we need to add gcc
some parameters to indicate the static library we want to link.
(Among them -I
- L
-l
, the content passed after it can be divided by adding spaces or not adding spaces)
-I
: Indicate the header file path we want to include
-L
: Indicate the path of the library we include
-l
: Indicate the library file name we want to include (the library file name here refers to the real name)
./test
Run our program and find that the program can start normally.
into the system's default search path
Linux
The default search path for the C/C++ header file system is: /usr/include
. The default search path
for the library file system of C/C++ is: and .Linux
/usr/lib64
/lib64
We move the file to the corresponding default search path:
At this point we compile ourmian.c
At this time, gcc
the compiler reports a link error, reminding us that the library cannot be found. At this time, because we are using a third-party library, we must specify the file name when compiling!
After specifying the path, we can compile normally!
Summary: Use of third-party libraries
- Need to specify the header file, and library file
- If it is not installed in the system by default
gcc
andg++
under the default search path, the user must specify the corresponding option to inform the compiler: a. where is the header file b. where is the library file c. who is the library file - Copy the library and header files we downloaded to the default path of the system,
Linux
which installation library! So what about uninstallation? For any software, the essence of installation and uninstallation is to copy it to the system-specific path! - If the library we installed is a third-party library, we must use it normally, even if it has been installed in the system,
gcc
g++
we must-l
specify the name of the specific library!
3. Dynamic library
Dynamic library : The code of the dynamic library is only linked when the program is running, and multiple programs share the code of the library. If we delete the dynamic library, the executable programs generated using the dynamic library will not be able to run!
We no longer need ar
commands when we make a dynamic library, we need the following two steps:
- Add parameters when
gcc
forming binary files-fPIC
, so that the resulting redirectable binary files will form position-independent codes. - Then
gcc
add-shared
parameters to package all retargetable binary files with position-independent codes to form a dynamic library.
Let's take a look at our directory structure:
Form a position-independent code:
Mark as a dynamic library:
When we have a dynamic library, we can delete the redirectable binary file, but the dynamic library cannot be deleted. If the dynamic library is deleted, the programs that depend on this dynamic library will not be able to run!
Next, we try to use the dynamic library to link to form an executable program:
Note: The library we wrote ourselves is a third-party library. When we want to compile, we must specify: header file path, library file path, library file name (real name).
4. The use of dynamic libraries
You can see that we have successfully compiled using the dynamic library, let's run our program.
An error has occurred, and the system prompts us that there is no way to find the dynamic library when the program is running. Why?
This is related to the characteristics of the dynamic library. Since the program using the dynamic library only links the code of the dynamic library when it is running, multiple programs share the code of the library, so the running program must know where to link our library. , that is, for the dynamic library, we need to tell the compiler where to link the library to compile during compilation, and to tell the operating system where to link the library to run during operation.
The static library does not need to be linked because: the binary code used by the user is directly copied to the target executable program during the compilation and linking of the static library. The compiled program is a complete program, and there is no need to use the static library at runtime.
There are three ways to solve the problem that the operating system cannot find the dynamic library:
environment variable
Linux
There is an environment variable under us LD_LIBRARY_PATH
: , the operating system will go to the path under this environment variable to search for dynamic libraries, we can add our third-party libraries to this environment variable, and then we can run our executable program It worked.
Execute our program:
The program executed successfully!
But we all know that environment variables are only valid within one login. If we use the environment variable method, we will still not be able to run the next time we log in, so this method is temporary.
soft link
We know that Linux
the default library path of C/C++ in Chinese is /usr/lib64
or /lib64
, which is also the default path for the system to search for libraries. We can create a soft link for our third-party library under this directory (it is not recommended to directly copy the third-party library to the default library path /usr/lib64
or /lib64
below), so that we can also use it normally.
Execute our program, run normally, soft link a better way to find the library directory.
Modify the configuration file
Linux
There is a configuration file directory in our /etc/ld.so.conf.d
system. In this directory, we can create a file and write the path of the dynamic library in the file, so that our system will also search for the path when searching for the dynamic library.
Create the file and fill in our paths:
In this way, we have finished modifying the configuration file, but we still need to make the configuration file take effect immediately, we can use ldconfig
the command.
Once everything is ready we can run our program!
3. Loading of dynamic and static libraries
1. Loading of static library
During the linking of the executable program, the code in the static library will be directly copied into the executable program. Therefore, the static library can be understood as not being loaded during the running of the program, or the static library is loaded together with the program.
However, because it is a static library, when multiple processes contain the same static library, it will cause a lot of duplicate code in the memory, resulting in a waste of memory resources.
2. Loading of dynamic library
When a program using a dynamic library uses a method in the library, a mark will be left at the place of use. When the program is dynamically linked after running, this mark will be replaced with the address in the dynamic library.
When a process A that uses a dynamic library runs and needs a dynamic library a, the operating system will first search for a in the memory, whether it exists, and if it exists, directly map a into the process address of process A through the page table In the shared area in the space, if it does not exist, the dynamic library a in the disk will be loaded into the memory, and then mapped through the page table.
We know that the compiled program has an address inside! The address inside the dynamic library is not an absolute address, but an offset! (relative address)
Because different processes have different levels of operation, the third library that needs to be used is destined to be different, and the free position in the shared space of each process is also uncertain! If absolute addressing is used, address conflicts may occur when a process uses multiple libraries!
When a dynamic library is actually mapped into the address space, its starting address can be truly determined! At this time, the address of the method in the dynamic library is equal to the address of the library plus its own offset in the library. Through this design method, the dynamic library can be loaded at will in the address space of the process, we can all find the methods in the library, and it will not conflict with other libraries! This is position-independent code .
4. Some other conclusions
- Dynamic library and static library exist at the same time, and the system uses dynamic link by default
- Generally speaking, when an executable program is generated, it will link multiple libraries. We can use
ldd
commands to check which libraries our program is linked to. The executable program can also choose to use some dynamic libraries and some static libraries when connecting. - If we
gcc
add-static
parameters to it,gcc
it will help us link the library by static linking by default.