当前位置: 技术问答>linux和unix
编译方式不同,结果完全不同,为什么?
来源: 互联网 发布时间:2016-03-12
本文导语: //sharelib.cpp #include class class1 { public: int mem1; class1(int iin1) { mem1 = iin1; }; }; int g_int(5); class1 g_class1(12); void printclass() { printf("g_class1.mem1 = %d n", g_class1.mem1); printf("g_int = %d n", g_int); } //main.cpp ...
//sharelib.cpp
#include
class class1
{
public:
int mem1;
class1(int iin1)
{ mem1 = iin1; };
};
int g_int(5);
class1 g_class1(12);
void printclass()
{
printf("g_class1.mem1 = %d n", g_class1.mem1);
printf("g_int = %d n", g_int);
}
//main.cpp
#include
extern void printclass();
int main(int argc, char** argv)
{
printclass();
return 0;
}
都是采用动态库
编译方式1:
c++ -shared -omylib.so sharelib.cpp
c++ -c main.cpp
c++ -omain1 -L. ./mylib.so main.o
./main1
输出为
g_class1.mem1 = 12
g_int = 5
编译方式2:
c++ -c sharelib.cpp
ld -omylib.so -shared sharelib.o sharelib2.o
c++ -c main.cpp
c++ -omain1 -L. ./mylib.so main.o
./main1输出为
g_class1.mem1 = 0
g_int = 5
仅仅一个编译不同,结果造成一个全局的类变量没有初始化,为什么?
#include
class class1
{
public:
int mem1;
class1(int iin1)
{ mem1 = iin1; };
};
int g_int(5);
class1 g_class1(12);
void printclass()
{
printf("g_class1.mem1 = %d n", g_class1.mem1);
printf("g_int = %d n", g_int);
}
//main.cpp
#include
extern void printclass();
int main(int argc, char** argv)
{
printclass();
return 0;
}
都是采用动态库
编译方式1:
c++ -shared -omylib.so sharelib.cpp
c++ -c main.cpp
c++ -omain1 -L. ./mylib.so main.o
./main1
输出为
g_class1.mem1 = 12
g_int = 5
编译方式2:
c++ -c sharelib.cpp
ld -omylib.so -shared sharelib.o sharelib2.o
c++ -c main.cpp
c++ -omain1 -L. ./mylib.so main.o
./main1输出为
g_class1.mem1 = 0
g_int = 5
仅仅一个编译不同,结果造成一个全局的类变量没有初始化,为什么?
|
原因是用c++链接的时候会链接libstdc++.so这样, 给就mylib.so加入两个重要的符号_init和_fini,
这样, 在装入器装入mylib.so时寻找并执行_init进行初始化, _init 通常也会调用libstdc++.so中的初始化例程.
用ld链接就不会有_init符号, 装入器找不到_init符号, 就不会执行class1的构造函数.
至于g_int变量,由于是普通的全局变量,被放在已初始化的数据段,
运行时的值由装入器从文件mylib.so数据段读如内存的.
但是class1不一样, 是一个类, 是放在未初始化数据段(BSS)的, 它的初始化需要执行构造函数
这一点与内置类型的变量是不同的.
上面提到的_init和_fini可以用
以下是一个例子的输出: 其中D表示符号位于已初始化的数据段, B表示符号位于未初始化的数据段.
[code=BatchFile]
+ uname -msrv
Linux 2.6.20 #1 SMP Thu Feb 14 18:08:17 CST 2008 x86_64
+ c++ -shared -o libshare.so -fPIC share.cc
+ c++ -c -fPIC main.cc
+ c++ -o main ./libshare.so main.o
+ c++ -c -fPIC share.cc
+ c++ -shared -o libshare2.so share.o
+ c++ -c -fPIC main.cc
+ c++ -o main2 ./libshare2.so main.o
+ c++ -c -fPIC share.cc
+ ld -shared -o libshare3.so share.o
+ c++ -c -fPIC main.cc
+ c++ -o main3 ./libshare3.so main.o
+ ./main
g_sh.mem = 12
g_int = 5
+ ./main2
g_sh.mem = 12
g_int = 5
+ ./main3
g_sh.mem = 0
g_int = 5
+ nm libshare.so
0000000000200ac0 d DW.ref.__gxx_personality_v0
00000000002008b0 a _DYNAMIC
0000000000200a88 a _GLOBAL_OFFSET_TABLE_
00000000000006cc t _GLOBAL__I_g_int
w _Jv_RegisterClasses
00000000000006e2 T _Z10printclassv
000000000000069c t _Z41__static_initialization_and_destruction_0ii
000000000000071c W _ZN5shareC1Ei
0000000000200888 d __CTOR_END__
0000000000200878 d __CTOR_LIST__
0000000000200898 d __DTOR_END__
0000000000200890 d __DTOR_LIST__
0000000000000870 r __FRAME_END__
00000000002008a0 d __JCR_END__
00000000002008a0 d __JCR_LIST__
0000000000200ac8 A __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000000740 t __do_global_ctors_aux
00000000000005f0 t __do_global_dtors_aux
00000000002008a8 d __dso_handle
w __gmon_start__
U __gxx_personality_v0@@CXXABI_1.3
0000000000200ac8 A _edata
0000000000200ad8 A _end
0000000000000778 T _fini
0000000000000570 T _init
00000000000005d0 t call_gmon_start
0000000000200ad0 b completed.6123
0000000000200ac8 b dtor_idx.6125
0000000000000670 t frame_dummy
0000000000200ab8 D g_int
0000000000200ad4 B g_sh
U printf@@GLIBC_2.2.5
+ nm libshare2.so
0000000000200ac0 d DW.ref.__gxx_personality_v0
00000000002008b0 a _DYNAMIC
0000000000200a88 a _GLOBAL_OFFSET_TABLE_
00000000000006cc t _GLOBAL__I_g_int
w _Jv_RegisterClasses
00000000000006e2 T _Z10printclassv
000000000000069c t _Z41__static_initialization_and_destruction_0ii
000000000000071c W _ZN5shareC1Ei
0000000000200888 d __CTOR_END__
0000000000200878 d __CTOR_LIST__
0000000000200898 d __DTOR_END__
0000000000200890 d __DTOR_LIST__
0000000000000870 r __FRAME_END__
00000000002008a0 d __JCR_END__
00000000002008a0 d __JCR_LIST__
0000000000200ac8 A __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000000740 t __do_global_ctors_aux
00000000000005f0 t __do_global_dtors_aux
00000000002008a8 d __dso_handle
w __gmon_start__
U __gxx_personality_v0@@CXXABI_1.3
0000000000200ac8 A _edata
0000000000200ad8 A _end
0000000000000778 T _fini
0000000000000570 T _init
00000000000005d0 t call_gmon_start
0000000000200ad0 b completed.6123
0000000000200ac8 b dtor_idx.6125
0000000000000670 t frame_dummy
0000000000200ab8 D g_int
0000000000200ad4 B g_sh
U printf@@GLIBC_2.2.5
+ nm libshare3.so
0000000000200648 d DW.ref.__gxx_personality_v0
00000000002004e8 a _DYNAMIC
0000000000200618 a _GLOBAL_OFFSET_TABLE_
00000000000003b8 t _GLOBAL__I_g_int
00000000000003ce T _Z10printclassv
0000000000000388 t _Z41__static_initialization_and_destruction_0ii
0000000000000408 W _ZN5shareC1Ei
0000000000200650 A __bss_start
U __gxx_personality_v0
0000000000200650 A _edata
0000000000200658 A _end
0000000000200640 D g_int
0000000000200650 B g_sh
U printf
[/code]
这样, 在装入器装入mylib.so时寻找并执行_init进行初始化, _init 通常也会调用libstdc++.so中的初始化例程.
用ld链接就不会有_init符号, 装入器找不到_init符号, 就不会执行class1的构造函数.
至于g_int变量,由于是普通的全局变量,被放在已初始化的数据段,
运行时的值由装入器从文件mylib.so数据段读如内存的.
但是class1不一样, 是一个类, 是放在未初始化数据段(BSS)的, 它的初始化需要执行构造函数
这一点与内置类型的变量是不同的.
上面提到的_init和_fini可以用
以下是一个例子的输出: 其中D表示符号位于已初始化的数据段, B表示符号位于未初始化的数据段.
[code=BatchFile]
+ uname -msrv
Linux 2.6.20 #1 SMP Thu Feb 14 18:08:17 CST 2008 x86_64
+ c++ -shared -o libshare.so -fPIC share.cc
+ c++ -c -fPIC main.cc
+ c++ -o main ./libshare.so main.o
+ c++ -c -fPIC share.cc
+ c++ -shared -o libshare2.so share.o
+ c++ -c -fPIC main.cc
+ c++ -o main2 ./libshare2.so main.o
+ c++ -c -fPIC share.cc
+ ld -shared -o libshare3.so share.o
+ c++ -c -fPIC main.cc
+ c++ -o main3 ./libshare3.so main.o
+ ./main
g_sh.mem = 12
g_int = 5
+ ./main2
g_sh.mem = 12
g_int = 5
+ ./main3
g_sh.mem = 0
g_int = 5
+ nm libshare.so
0000000000200ac0 d DW.ref.__gxx_personality_v0
00000000002008b0 a _DYNAMIC
0000000000200a88 a _GLOBAL_OFFSET_TABLE_
00000000000006cc t _GLOBAL__I_g_int
w _Jv_RegisterClasses
00000000000006e2 T _Z10printclassv
000000000000069c t _Z41__static_initialization_and_destruction_0ii
000000000000071c W _ZN5shareC1Ei
0000000000200888 d __CTOR_END__
0000000000200878 d __CTOR_LIST__
0000000000200898 d __DTOR_END__
0000000000200890 d __DTOR_LIST__
0000000000000870 r __FRAME_END__
00000000002008a0 d __JCR_END__
00000000002008a0 d __JCR_LIST__
0000000000200ac8 A __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000000740 t __do_global_ctors_aux
00000000000005f0 t __do_global_dtors_aux
00000000002008a8 d __dso_handle
w __gmon_start__
U __gxx_personality_v0@@CXXABI_1.3
0000000000200ac8 A _edata
0000000000200ad8 A _end
0000000000000778 T _fini
0000000000000570 T _init
00000000000005d0 t call_gmon_start
0000000000200ad0 b completed.6123
0000000000200ac8 b dtor_idx.6125
0000000000000670 t frame_dummy
0000000000200ab8 D g_int
0000000000200ad4 B g_sh
U printf@@GLIBC_2.2.5
+ nm libshare2.so
0000000000200ac0 d DW.ref.__gxx_personality_v0
00000000002008b0 a _DYNAMIC
0000000000200a88 a _GLOBAL_OFFSET_TABLE_
00000000000006cc t _GLOBAL__I_g_int
w _Jv_RegisterClasses
00000000000006e2 T _Z10printclassv
000000000000069c t _Z41__static_initialization_and_destruction_0ii
000000000000071c W _ZN5shareC1Ei
0000000000200888 d __CTOR_END__
0000000000200878 d __CTOR_LIST__
0000000000200898 d __DTOR_END__
0000000000200890 d __DTOR_LIST__
0000000000000870 r __FRAME_END__
00000000002008a0 d __JCR_END__
00000000002008a0 d __JCR_LIST__
0000000000200ac8 A __bss_start
w __cxa_finalize@@GLIBC_2.2.5
0000000000000740 t __do_global_ctors_aux
00000000000005f0 t __do_global_dtors_aux
00000000002008a8 d __dso_handle
w __gmon_start__
U __gxx_personality_v0@@CXXABI_1.3
0000000000200ac8 A _edata
0000000000200ad8 A _end
0000000000000778 T _fini
0000000000000570 T _init
00000000000005d0 t call_gmon_start
0000000000200ad0 b completed.6123
0000000000200ac8 b dtor_idx.6125
0000000000000670 t frame_dummy
0000000000200ab8 D g_int
0000000000200ad4 B g_sh
U printf@@GLIBC_2.2.5
+ nm libshare3.so
0000000000200648 d DW.ref.__gxx_personality_v0
00000000002004e8 a _DYNAMIC
0000000000200618 a _GLOBAL_OFFSET_TABLE_
00000000000003b8 t _GLOBAL__I_g_int
00000000000003ce T _Z10printclassv
0000000000000388 t _Z41__static_initialization_and_destruction_0ii
0000000000000408 W _ZN5shareC1Ei
0000000000200650 A __bss_start
U __gxx_personality_v0
0000000000200650 A _edata
0000000000200658 A _end
0000000000200640 D g_int
0000000000200650 B g_sh
U printf
[/code]