Link (extern, static keyword \ header file \ Static library \ Shared library)

Source: Internet
Author: User

Original link: http://www.orlion.ga/781/

I. Links to multi-objective files

Suppose there are two files: stack.c:

/* STACK.C */char stack[512];int top = -1;void push (char c) {stack[++top] = C;} Char pop (void) {return stack[top--];} int Is_empty (void) {return top = =-1;}

The above file implements the stack. MAIN.C:

/* MAIN.C */#include <stdio.h>int main (void) {push (' a ');        Push (' B ');                Push (' C ');        while (!is_empty ()) Putchar (pop ());        Putchar (' \ n '); return 0;}

This file is used by the stack, compiled: gcc main.c stack.c-o Main, can also be compiled in step:

Gcc-c main.cgcc-c STACK.CGCC main.o stack.o-o Main

Using the NM command to view the symbol table of the target file, you will find undefined symbol push, pop, Is_empty, Putchar in MAIN.O. The first three symbols are implemented in STACK.O, which can be symbolic parsed when the link is delivered to the executable main, while Putchar is the LIBC library function, in the executable file main

Still undefined, do dynamic linking while the program is running.

We can see by readelf-a the main command, The. BSS segment of main incorporates the. BSS segment of MAIN.O and STACK.O, which contains the. Data segment of variables A and Stack,main also incorporates the. Data segment of the MAIN.O and STACK.O, which contains the variables B and top,main. Text segment merges MAIN.O and S TACK.O. Text segment that contains the definitions of each function. As shown in the following:

If you put STACK.O in front of MAIN.O at compile time, that is: gcc stack.o main.o-o Main, the executable file from the MAIN.O variable or function in each paragraph of main is discharged to the back.

II. Definitions and declarations

1. extern and Static keywords

There is a small problem when compiling stack.c and main.c files above, (-wall option can be seen) because the compiler does not find a function prototype when processing the function call code, it has to make an implicit declaration according to the function call code, declare three functions as

int push (char), int pop (void), int is_empty (void);

Now complete the code in one:

/* MAIN.C */#include <stdio.h>extern void push (char), extern char pop (void), extern int is_empty (void), int main (void        ) {push (' a ');        Push (' B ');                Push (' C ');        while (!is_empty ()) Putchar (pop ());        Putchar (' \ n '); return 0; }

So the compiler will not report the alarm, the extern keyword indicates that the identifier has external Linkage ("extern keyword indicates that this identifier has external Linkage" is actually inaccurate, it should be previous Linkage. The definition of Previous linkage is that the identifier for this declaration has a linkage depending on the previous declaration, which has the same identifier name as the previous declaration, and must be a file scope declaration if the previous declaration was not found in the program file (this is the first declaration). Then this identifier has external Linkage), and the push identifier has external Linkage refers to: if MAIN.C and STACK.C are linked together, if push is declared in MAIN.C and STACK.C ( In STACK.C is both a declaration and a definition) then these declarations refer to the same function, followed by the same global symbol, representing the same address.

The extern in the function declaration can also be omitted from the write, the non-write extern still indicates that this function name has external Linkage. The C language does not allow nested definition functions, but if they are declared but not defined, such declarations are allowed to be written inside the function body, so that the declared identifiers have block scopes, such as the main.c above can be written as:

/* MAIN.C */#include <stdio.h>int main (void) {void push (char);        Char pop (void);        int is_empty (void);        Push (' a ');        Push (' B ');                Push (' C ');        while (!is_empty ()) Putchar (pop ());        Putchar (' \ n '); return 0;}

If you decorate a function declaration with the Stati keyword, it means that the identifier has internal Linkage, for example, there are two program files:

/* foo.c */static void foo (void) {}

/* MAIN.C */void foo (void); int main (void) {foo (); return 0;}

Compiling links together makes an error:

Although function foo is defined in foo.c, this function only has internal Linkage, which is represented by multiple declarations in foo.c, and is not represented in MAIN.C. If the foo.c compiled into a target file, the function name Foo in which is a local symbol, do not participate in the link process, so at the link, main.c with a external linkage foo function, the linker can not find its definition where, unable to determine its address, Also can not do symbolic resolution, only error. A variable or function that is declared more than once must have and only one declaration is defined, and if there is more than one definition, or none of the definitions, the linker cannot complete the link.

For variables, if you use the extern int top in the main () function in Main.c, declare the top variable to have access to the top variable in the STACK.C. (the extern declaration of a variable cannot be omitted and cannot be defined such as: extern int top =-1; it is incorrect to write). If you don't want MAIN.C access to the top variable, you can declare top with static, static int top =-1 in stack.c;

2. header file

(i) The STACK.C module encapsulates the top and stack two variables exported push\pop\is_empty three function interfaces, but each program file using this module to write three function declarations, assuming that another file also uses the module, then write three function declarations. This time you can write a header file Stack.h to simplify the code:

/* stack.h */#ifndef stack_h#define stack_hextern void push (char), extern char pop (void), extern int is_empty (void); #endif

It is only necessary to include in the MAIN.C:

/* MAIN.C */#include <stdio.h> #include "stack.h" int main (void) {push (' a ');        Push (' B ');                Push (' C ');        while (!is_empty ()) Putchar (pop ());        Putchar (' \ n '); return 0;}

For header files included with angle brackets (#include <stdio.h>) GCC first looks for the directory specified by the-I option and then looks at the system's header file directory (usually/usr/include), and for the header file included in the quotation marks, GCC first finds the directory where the. c file contains the header file, and then looks for the directory specified by the-I option, and then finds the system's header file directory. Relative path strength can be used in # include preprocessing such as: #include "header/stack.h"

#idndef Stack_h and #endif is if STACK_H this macro is not defined, then the code between the #ifndef to #endif is included in the preprocessed output, otherwise this piece of code will not be in the output of the preprocessing now. Stack.h the contents of this header file are all contained in #ifndef and #endif, and if STACK_H the macro is already defined when the header file is included, it is equivalent to nothing in this file.

There is also a problem, since to include the header file, then I might as well directly in the MAIN.C # # # "Stack.c" got. This merges stack.c and main.c into the same program file. Although this can be compiled through, but in a larger project can not do so, if there is a foo.c also want to use STACK.C this module how to do? If in foo.c also include "stack.c", equivalent to push, pop, is_empty these three functions are defined in MAIN.C and foo.c, then main.c and foo.c can not be linked together. If you adopt a method that contains a header file, then these three functions are defined only once in the STACK.C, and finally can be

To link main.c, STACK.C and foo.c together.


Third, Static library

Sometimes to compile a set of code into a library, this library is used in many projects, such as libc is such a library, we will use in different programs in the LIBC library functions (such as printf) also used in libc variables (such as environ)

Split the STACK.C in (a) into four files:

/* STACK.C */char stack[512];int top =-1;

/* push.c */extern char stack[512];extern int top;void push (char c) {stack[++top] = C;}

/* pop.c */extern char stack[512];extern int top;char pop (void) {return stack[top--];}

/* is_empty.c */extern int top;int is_empty (void) {return top = =-1;}
/* stack.h */#ifndef stack_h#define stack_hextern void push (char), extern char pop (void), extern int is_empty (void); #endif
/* MAIN.C */#include <stdio.h> #include "stack.h" int main (void) {push (' a '); return 0;}

The directory structure is:

|–main.c

|–stack

|–is_empty.c

|–pop.c

|–push.c

|–stack.c

|–stack.h

Compile stack.c, push.c, POP.C, is_empty.c into the target file:

Gcc-c stack/stack.c stack/push.c stack/pop.c stack/is_empty.c

Then package it into a static library libstack.a:

Ar rs libstack.a stack.o push.o pop.o is_empty.o

The library files are all beginning with lib, and the static library is suffixed with. A, which indicates archive. The AR command, like the tar command, acts as a wrapper, but packaging the target file into a static library can only be used with the AR command instead of the tar command. The option R indicates that the file list is added to the package, and if the package does not exist, it is created if the package already has a file with the same name replaced by the new one. S is dedicated to generating static libraries, which represent the creation of indexes for static libraries, which are used by the linker. The Ranlib command can also create an index for a static library, which is equivalent to the following:

AR r libstack.a stack.o push.o POP.O is_empty.oranlib libstack.a

Then the LIBSTACK.A and MAIN.C are compiled to join together:

GCC main.c-l.-L stack-i Stack-o Main

The-l option tells the compiler where to find the required library file,-L. Indicates that it is looking in the current directory. -lstack tells the compiler to link the Libstack library, the-i option tells the compiler where to go to your change files. Note that even if the library file is in the current directory, the compiler will not look for it by default, so the-l option cannot be reduced. The directory that the compiler will look for by default can be viewed with the-print-search-dirs option.

The compiler will first find there is no shared library libstack.so, if there is a link to it, if there is no static library libstack.a, if there is a link to it. So the compiler takes precedence over shared libraries, and if you want the compiler to link only static libraries, you can specify the-static option.

When you link libc shared library just specify the dynamic linker and the library file required by the program, and do not really do the link, the executable file called in Main libc library function is still undefined symbol, to do dynamic link at run time. When linking to a static library, the linker pulls the target file from the static library and actually links it to the executable.

Iv. Shared libraries

1, compile, link, run

The target file that makes up the shared library differs from the generic target file, and the-fpic option is added at compile time:

Gcc-c-fpic stack/stack.c stack/push.c stack/pop.c stack/is_empty.c

The-F followed by the compile option, pic is one of the sources that represents the generate location-independent code. The general target file is called relocatable, in the link can be the target file in the address of the various segments of the relocation, relocation needs to modify the instructions.

Now link the main.c with the shared library compilation, and then run:

$ gcc main.c-g-l-lstack-istack-o main$./main/main:error while loading shared libraries:libstack.so:cannot open Shared object File:no such file or directory

(TODO: There is a problem with the native experiment here)

When compiling, the compiler can find libstack.so in the current directory because the-l option is specified, while the runtime says libstack.so cannot be found.

You can use the LDD command to see which shared libraries the executable file depends on:

$ LDD Main linux-gate.so.1 = (0xb7f5c000) libstack.so = not found libc.so.6 =/lib/tls/i 686/cmov/libc.so.6 (0xb7dcf000)/lib/ld-linux.so.2 (0xb7f42000)

The LDD simulation runs through main and makes dynamic links during the run so that the executable is dependent on which shared libraries, and under what path each shared library is loaded into the address space of the process. /lib/ld-linux.so.2 is a dynamic linker whose path is specified when the link is compiled, and GCC uses-dynamic-linker to specify the path to the dynamic linker when it makes the link, and it loads into the address space of the process like any other shared library. The path of the libc.so.6 is/lib/tls/i686/cmov/libc.so.6 by the dynamic linker ld-linux.so.2 when the dynamic link is made, and the libstack.so path is not found. Linux-gate.so.1 This shared library does not actually exist in the file system, it is a shared library that is virtual by the kernel, so it has no corresponding path, it is responsible for handling system calls. In summary, the search path for a shared library is determined by the dynamic linker, and the search order for shared library paths can be found from the ld.so (8) man page:

1. First look in the path recorded by the environment variable Ld_library_path.

2. Then look it up from the cache file/etc/ld.so.cache. This cache file is read by the Ldconfig command

/etc/ld.so.conf after the pieces are generated, explained in detail later.

3. If none of the above steps are found, then look in the default system path, first/usr/lib and then/lib.

Workaround: You can add the absolute path of the directory where the libstack.so resides to/etc/ld.so.conf, and then run the Ldconfig

2. Naming conventions for shared libraries

According to the naming convention for shared libraries, each shared library has three file names: real name, soname, and linker name. The name of the real library file (instead of the symbolic link) is the real name, which contains the full shared library version number. such as the above libcap.so.1.10, libc-2.8.90.so and so on. Soname is a symbolic link name that contains only the major version number of the shared library, the major version number is consistent to ensure that the library function interface is consistent, so the application's. Dynamic segment only records the soname of the shared library, as long as soname consistent, the shared library can be used. For example, the libcap.so.1 and libcap.so.2 above are two different libcap with major version numbers, some applications

Depending on libcap.so.1, some applications rely on libcap.so.2, but for applications that rely on libcap.so.1, the real library files can be used either libcap.so.1.10 or libcap.so.1.11, so using a shared library makes it easy to upgrade Cuven No need to recompile the application, which is not an advantage of the static library. Note that the version number of the libc is a bit special, and the libc-2.8.90.so major version number is 6 instead of 2 or 2.8.

Linker name is used only when compiling links, the-l option for GCC should specify the directory where linker name resides. Some linker

Name is a symbolic link to the library file, and some linker name is a link script

Link (extern, static keyword \ header file \ Static library \ Shared library)

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.