动态库和静态库作为两种不同的解决程序代码复用(为了复用而在内存中的存在方式)的手段而并行不悖,各有千秋
前者动态绑定(运行期),节约空间,利于维护
后者静态绑定(编译期),独立运行,不产生运行依赖
下面以示例来说明:
先看静态库
/*************************************************************************
> File Name: sxyqe.cpp
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Sun 24 Sep 2017 06:10:41 PM CST
************************************************************************/
#include<iostream>
using namespace std;
void sxyqe(void)
{
cout << "山下一群鹅," << endl;
}
/*************************************************************************
> File Name: xsglh.cpp
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Sun 24 Sep 2017 06:13:18 PM CST
************************************************************************/
#include<iostream>
using namespace std;
void xsglh(void)
{
cout << "嘘声赶落河。" << endl;
}
将 sxyqe.cpp 和 xsglh.cpp 编译为静态库:
g++ -c sxyqe.cpp xsglh.cpp
ar rcs libA.a sxyqe.o xsglh.o查看:
nm -a libA.a
sxyqe.o:
0000000000000000 b .bss
0000000000000000 n .comment
U __cxa_atexit
0000000000000000 d .data
U __dso_handle
0000000000000000 r .eh_frame
0000000000000061 t _GLOBAL__sub_I__Z5sxyqev
0000000000000000 t .init_array
0000000000000000 n .note.GNU-stack
0000000000000000 r .rodata
0000000000000000 a sxyqe.cpp
0000000000000000 t .text
0000000000000023 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 T _Z5sxyqev
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
xsglh.o:
0000000000000000 b .bss
0000000000000000 n .comment
U __cxa_atexit
0000000000000000 d .data
U __dso_handle
0000000000000000 r .eh_frame
0000000000000061 t _GLOBAL__sub_I__Z5xsglhv
0000000000000000 t .init_array
0000000000000000 n .note.GNU-stack
0000000000000000 r .rodata
0000000000000000 t .text
0000000000000000 a xsglh.cpp
0000000000000023 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 T _Z5xsglhv
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
可以看到尽管我们将这两个源文件编译为静态库形式,U 标识的项依然是依赖于c++的动态库,也就
是该静态库依赖于c++标准库,链接过程中会去c++库查找符号如:cout
-----------------------------------------------------------------------------------------------------------------------------------
接下来是动态库/*************************************************************************
> File Name: lhzeyde.cpp
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Sun 24 Sep 2017 06:31:18 PM CST
************************************************************************/
#include<iostream>
using namespace std;
void lhzeyde(void)
{
cout << "落河捉鹅医肚饿," << endl;
}
/*************************************************************************
> File Name: cwhjwlp.cpp
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Sun 24 Sep 2017 06:33:09 PM CST
************************************************************************/
#include<iostream>
using namespace std;
void cwhjwlp(void)
{
cout << "吃完回家玩老婆。" << endl;
}
将lhzeyde.cpp 和 cwhjwlp.cpp 编译为动态库:
gcc -fPIC -shared -o libB.so lhzeyde.cpp cwhjwlp.cpp
查看:
nm -a libB.so
0000000000000000 a
0000000000201040 b .bss
0000000000201040 B __bss_start
0000000000000000 n .comment
0000000000201040 b completed.7585
0000000000000000 a crtstuff.c
0000000000000000 a crtstuff.c
0000000000000000 a cwhjwlp.cpp
U __cxa_atexit@@GLIBC_2.2.5
w __cxa_finalize@@GLIBC_2.2.5
0000000000201038 d .data
0000000000000810 t deregister_tm_clones
00000000000008a0 t __do_global_dtors_aux
0000000000200df0 t __do_global_dtors_aux_fini_array_entry
0000000000201038 d __dso_handle
0000000000200e00 d .dynamic
0000000000200e00 d _DYNAMIC
0000000000000428 r .dynstr
0000000000000230 r .dynsym
0000000000201040 D _edata
0000000000000ab0 r .eh_frame
0000000000000a6c r .eh_frame_hdr
0000000000201048 B _end
0000000000000a30 T _fini
0000000000000a30 t .fini
0000000000200df0 t .fini_array
00000000000008e0 t frame_dummy
0000000000200dd8 t __frame_dummy_init_array_entry
0000000000000bb0 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
0000000000000a1b t _GLOBAL__sub_I_cwhjwlp.cpp
000000000000098b t _GLOBAL__sub_I_lhzeyde.cpp
w __gmon_start__
0000000000000a6c r __GNU_EH_FRAME_HDR
00000000000001f0 r .gnu.hash
00000000000005ae r .gnu.version
00000000000005d8 r .gnu.version_r
0000000000200fc0 d .got
0000000000201000 d .got.plt
0000000000000790 T _init
0000000000000790 t .init
0000000000200dd8 t .init_array
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000200df8 d .jcr
0000000000200df8 d __JCR_END__
0000000000200df8 d __JCR_LIST__
w _Jv_RegisterClasses
0000000000000000 a lhzeyde.cpp
00000000000001c8 r .note.gnu.build-id
00000000000007b0 t .plt
0000000000000800 t .plt.got
0000000000000850 t register_tm_clones
00000000000005f8 r .rela.dyn
0000000000000730 r .rela.plt
0000000000000a39 r .rodata
0000000000000810 t .text
0000000000201040 d __TMC_END__
0000000000000942 t _Z41__static_initialization_and_destruction_0ii
00000000000009d2 t _Z41__static_initialization_and_destruction_0ii
00000000000009a0 T _Z7cwhjwlpv
0000000000000910 T _Z7lhzeydev
U _ZNSolsEPFRSoS_E
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
U _ZSt4cout
U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000201041 b _ZStL8__ioinit
0000000000201042 b _ZStL8__ioinit
U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
同样从U标识的未定义符号可以看到,该动态库依赖于c++动态库
/*************************************************************************
> File Name: main.cpp
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Sun 24 Sep 2017 06:43:53 PM CST
************************************************************************/
#include<iostream>
#include"sxyqe.h"
#include"xsglh.h"
#include"lhzeyde.h"
#include"cwhjwlp.h"
using namespace std;
int main()
{
cout << "===================================================================" << endl;
cout << "祝枝山:今天我们江南四大才子到这里游山玩水,难怪那些女子要疯狂了。" << endl;
cout << "~~~~~~:说得是," << endl;
cout << "文征明:各位各位,既然大家今天兴致这么好,不如来吟首诗如何? " << endl;
cout << "祝枝山:哎,征明兄提议的好啊。文斌兄你先来。 " << endl;
cout << "文 斌:";
sxyqe();
cout << "文征明:";
xsglh();
cout << "祝枝山:";
lhzeyde();
cout << "唐伯虎:";
cwhjwlp();
cout << "三 人:哎呀,对得妙呀,真是绝句!" << endl;
cout << "唐伯虎:啊哈哈" << endl;
cout << "===================================================================" << endl;
return 0;
}
测试:
g++ main.cpp -I../libar -I../libso -L../libar -L../libso -lA -lB -o main
如果多个库之间有依赖,为确保依赖次,序应该将被依赖的库放在该库之前
结果:
附: nm 各输出项含义
For each symbol, nm shows: The symbol value, in the radix selected by options (see below), or hexadecimal by default. The symbol type. At least the following types are used; others are, as well, depending on the object file format. If lowercase, the symbol is usually local; if uppercase, the symbol is global (external). There are however a few lowercase symbols that are shown for special global symbols (u, v and w). --A The symbol’s value is absolute, and will not be changed by further linking.
bThe symbol is in the uninitialized data section (known as BSS).--B
The symbol is common. Common symbols are uninitialized data. When linking, multiple common symbols may appear with the same name. If the symbol is defined anywhere, the common symbols are treated as undefined references. For more details on common symbols, see the discussion of –warn-common in Linker options in The GNU linker.--C
dThe symbol is in the initialized data section.--G gThe symbol is in an initialized data section for small objects. Some object file formats permit more efficient access to small data objects, such as a global int variable as opposed to a large global array.--iFor PE format files this indicates that the symbol is in a section specific to the implementation of DLLs. For ELF format files this indicates that the symbol is an indirect function. This is a GNU extension to the standard set of ELF symbol types. It indicates a symbol which if referenced by a relocation does not evaluate to its address, but instead must be invoked at runtime. The runtime execution will then return the value to be used in the relocation.--IThe symbol is an indirect reference to another symbol.--NThe symbol is a debugging symbol.--pThe symbols is in a stack unwind section.--R rThe symbol is in a read only data section.--S sThe symbol is in an uninitialized data section for small objects.--T tThe symbol is in the text (code) section.--UThe symbol is undefined.--uThe symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use.--V vThe symbol is a weak object. When a weak defined symbol is linked with a normal defined symbol, the normal defined symbol is used with no error. When a weak undefined symbol is linked and the symbol is not defined, the value of the weak symbol becomes zero with no error. On some systems, uppercase indicates that a default value has been specified.--W wThe symbol is a weak symbol that has not been specifically tagged as a weak object symbol. When a weak defined symbol is linked with a normal defined symbol, the normal defined symbol is used with no error. When a weak undefined symbol is linked and the symbol is not defined, the value of the symbol is determined in a system-specific manner without error. On some systems, uppercase indicates that a default value has been specified. -The symbol is a stabs symbol in an a.out object file. In this case, the next values printed are the stabs other field, the stabs desc field, and the stab type. Stabs symbols are used to hold debugging information. ?The symbol type is unknown, or object file format specific.--D