当前位置:  技术问答>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


仅仅一个编译不同,结果造成一个全局的类变量没有初始化,为什么?



|
原因是用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]

    
 
 

您可能感兴趣的文章:

  • 我用的是atmel一个成熟的开发板。有一个触摸屏驱动程序,以<M>的方式编译为模块,编译时提示某个外部函数没有定义,但如果以<*>的方式编译进内核,则不会出错。请教下可能是什么原因?
  • 如何查看编译方式安装的软件!
  • 关于嵌入式Linux固件中内核编译通常采用哪种优化方式
  • 请问:编译线程程序时,命令数是写成 -lpthread 还是写成-l pthread啊,怎么两种方式都可以啊,谁是标准的呢?
  • 在JBuilder 5.0中,我打开一个单独的java文件,怎么编译和运行他?用命令行方式是可以的
  • 请介绍一些能进行以JIT(Just In Time)方式编译的工具.
  • 如何让gcc的编译错误信息以英文的方式输出?
  • 下面的java程序我想用命令行的方式进行编译
  • Linux编译安装vsftpd服务器(本地用户验证方式)
  • 关于如何判断gcc之类的编译器的编译结果?
  • 如果重新编译了.so文件后,但程序运行结果还是编译前的情况,大概是什么问题呢?
  • 在JBuilder 5.0中,我打开一个单独的java文件,怎么编译和运行他?用命令行方式是可以的 iis7站长之家
  • 用gcc编译c程序能通过,为何没执行结果?
  • 在cygwin中编译c,结果打不开stdio.h,如何解决!
  • linux下c++调用数学函数后,编译正确但不出结果
  • 编译问题,引用了别人的一个库,结果编译出问题。
  • 菜鸟问题:为什么我的程序编译之后看不到运行结果?
  • 为什么用IE打开applet,当我对java文件重新编译后,用F5刷新,还是原来的结果
  • 小试牛刀结果一头雾水!关于gcc编译后的a.out居然无法执行,系统说:我没有找到!:-(
  • 编译模块输出不了结果
  • 如何让java的编译时的错误信息或输出的结果信息显示在指定的窗口中
  • Linux 下怎么把程序编译的结果保存输出到一个文本文件中?是什么命令?
  • const类型重新赋值,编译通过,结果出乎意料,大家帮忙看看
  • 直接编译和在jcreator中执行的结果不一样???
  • 编译的程序双击运行和在命令行下运行为什么结果会不一样?
  • 一个简单的程序,编译可以通过但是,不出现结果,错误提示为无数个at Test.<init>(TestNonStatic.java:8),怎么回事
  • linux平台,线程的问题,编译结果为什么会这样
  • 请教:该类编译后运行的输出是什么,为什么会有这样的结果???
  • arm-elf-gcc 编译成功,但浮点运算结果是错的
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • linux/centos源码安装nginx编译配置选项参数介绍
  • 请教:JSP编译器编译成字节码,跟别的编译器编译出来的有什么不同呢?
  • CentOS 6内核升级:下载编译启用新内核版本详细过程
  • 编译GCC时能不能只编译C/C++的编译器?
  • 高速的网络抓包库PF_ring介绍及编译安装
  • 关于arm交叉编译器4.3.3编译程序报错,但是3.4.5却能编译通过的问题
  • JB下,我的程序编译得好慢!请问用什么方法编译才可以快一点?或编译顺序改变一下?
  • 请问gdb是不是只能调试gcc编译的程序,在unix下用其它编译器编译的程序是不是不一定能用gdb调试的?
  • 用JCreator写了一个小程序,有十几个class,当修改某个文件重新编译,javac并没有编译修改的文件,请问要如何做javac才会重新编译所有的
  • 问:关于gcc编译器和g++编译器
  • 嵌入式linux开发:一段代码在windows平台用VC编译运行正常,在linux平台用gcc编译运行正常,但是用arm-linux-gcc编译在嵌入式板子上运行就不正常.
  • 在cygwin编译驱动程序要不要交叉编译?
  • 关于如何把编译进内核的编译成模块
  • C编译器 c++编译器 wieldylcc
  • Linux下gcc编译时,如何以静态链接的形式编译?
  • PROC开发时 //注释编译不通过 如何设置使用cpp编译。
  • 编译失败后如何再继续编译
  • 编译qt-x11,最后编译生成可执行文件时候,make出错
  • 如何查看已编译安装软件的编译命令行
  • 请问哪里有反编译.class文件的反编译器?
  • 用Jdk编译时出现提示要加 -deprecation 再编译,请教??


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3