当前位置:  技术问答>linux和unix

为什么gcc可以连接archive中的多个同样的symbol,而没有报multiple definition?

    来源: 互联网  发布时间:2016-01-02

    本文导语:  1. why gcc can link objs with multiple same symbols after ar? what's the difference between it and linking before ar? 2. If multiple same symbols are allowable when linking, then what's the rule to resolve undefined function call(claimed with "ex...

1. why gcc can link objs with multiple same symbols after ar? what's the difference between it and linking before ar?
2. If multiple same symbols are allowable when linking, then what's the rule to resolve undefined function call(claimed with "extern" before)?

a.c:

extern int f();

int main()
...{
    printf("result is %d  ",f());
    return f();
}

int f()
...{
    return 1;
}

 b.c:

int f()
...{
    return 0;
}

test1:
>gcc -c a.c -o a.o
>nm -s a.o
00000030 T f
00000000 t gcc2_compiled.
00000000 T main
                   U printf
>gcc -c b.c -o b.o
>nm -s b.o
00000000 T f
00000000 t gcc2_compiled.
>gcc b.o a.o -o main                                   //link failed because of the same global symbols "f"
a.o: In function `f':
a.o(.text+0x30): multiple definition of `f'
b.o(.text+0x0): first defined here
collect2: ld returned 1 exit status
test2:
>ar cr b.a b.o
f in b.o
b.o:
00000000 T f
00000000 t gcc2_compiled.
>ar cr a.a a.o
Archive index:
main in a.o
f in a.o
a.o:
00000030 T f
00000000 t gcc2_compiled.
00000000 T main
                   U printf
>gcc b.a a.a -o main                              //link is sucessful!!! what's the difference between it and test1???
> main
result is 1                                                //why the result is 1???
 
--------------------------------------------------------------------------------------------------------------------------------------------
a1.c:
extern int f();

int main()
...{
    printf("result is %d  ",f());
    return f();
}

a2.c:
int f()
...{
    return 1;
}

b.c:

int f()
...{
    return 0;
}

 
> gcc -c a1.c -o a1.o
                   U f
00000000 t gcc2_compiled.
00000000 T main
                   U printf
> gcc -c a2.c -o a2.o
00000000 T f
00000000 t gcc2_compiled.
> gcc -c b.c -o b.o
00000000 T f
00000000 t gcc2_compiled.
> ar cr a2.a a2.o
> nm -s a2.a
Archive index:
f in a2.o
a2.o:
00000000 T f
00000000 t gcc2_compiled.
> ar cr b.a b.o
> nm -s b.a
Archive index:
f in b.o
b.o:
00000000 T f
00000000 t gcc2_compiled.
> ar cr a1.a a1.o
> nm -s a1.a
Archive index:
main in a1.o
a1.o:
                   U f
00000000 t gcc2_compiled.
00000000 T main
                   U printf
> ar cr a.a a2.o a1.o
> nm -s a.a
Archive index:
f in a2.o
main in a1.o
a2.o:
00000000 T f
00000000 t gcc2_compiled.
a1.o:
                   U f
00000000 t gcc2_compiled.
00000000 T main
                  U printf

test1:
> gcc b.a a.a -o main
> main
result is 1 
 
test2:
> gcc a1.a b.a a2.a -o main0
> gcc a2.a a1.a b.a -o main0
> main0
result is 0                                                //the result is dependent to link sequence!!!
> gcc a1.a a2.a b.a -o main1
> gcc b.a a1.a a2.a -o main1
> main1
result is 1                                               //the result is dependent to link sequence!!!

test3:
> gcc b.a a2.a a1.a -main                 //why this liinking failed???
a1.a(a1.o): In function `main':
a1.o(.text+0xd): undefined reference to `f'
a1.o(.text+0x25): undefined reference to `f'
collect2: ld returned 1 exit status

|
就我的经验而言,
gcc对待.o与.a是不同的,.a是所谓“静态库文件”,其实就是.o的一个集合,但是它被视作“函数体的提供者”,只要有可能,就尽量少去把它的成员连接到最终的可执行文件中,而命令行参数中普通的.o文件将完整地被连接到最终的可执行文件中去。

gcc在连接过程中,只在当前存在有Undefined 的symbol的时候,才会到参数list中的下一个.a里去找它的成员,如果一个成员(.o文件)没有提供要找的symbol,这个.o将不会被连接到最终的可执行文件中去;如果在某个.o中存在要找的symbol的定义体,那么这个.o将被整个连接进可执行文件(注意只连接了这个.o,它所属的.a中其他的.o文件不被连接),这一时刻,symbol表是有可能发生扩充的,也就是这个.o中的symbol将被整个引入当前的symbol表中,当然也就有可能增加Undefined的symbol;gcc在连接过程中,任一时刻发现没有Undefined的symbol存在,那么gcc将停止对.a的搜索。这就是为什么会出现明明两个.a中有同名symbol,却可以编译连接通过;同样可以说明,为什么你程序的运行结果会和参数顺序有关系,实际情况是,后一个.a并没有被连接进去。

此外在以上行为中,还隐藏了一个推断:gcc在连接过程,对.a的操作是严格有序的,也就是说,在搜索中由于未发现有用的symbol而被忽略(将不被连接到最终可执行文件中)了的.o,不会被再次扫描。那么如果在命令行参数的顺序中比较靠后的.a中有一个symbol没有定义,而该symbol的定义体所在的.o在之前也恰好被忽略了,那么gcc最终将无法定位这个symbol,也就会报出"undefined reference "这样的错误来。

for you information

    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 多个gcc,makefile如何指定
  • (只有10分了)如何用GCC编译多个文件啊
  • 请问一下,在gcc下如何连接多个文件,在线,特急。
  • 刚学linux,gcc 多个文件一起编译一个简单错误
  • Linux下GCC内置原子操作函数(多线程资源访问)介绍
  • 使用popen来执行gcc命令,如何根据读出来的gcc的输出来判断gcc是否编译成功?
  • 命令:mips_fp_le-gcc,mipsel-gcc 是什么意思?跟一般的gcc有什么区别?
  • 怎样升级我的GCC呀,我用的RH7.2,GCC 2.96 ,我从网上下载了一个gcc-3.2.3.tar.gz
  • arm-elf-gcc 和 arm-linux-gcc有什么区别?arm-elf-gcc里的elf代表什么?
  • gcc-ccore、avr-gcc及arm-gcc的区别
  • gcc在哪里?bash:gcc:command not found
  • 如何删掉GCC3.0(我需要GCC2.0-----)
  • Windows版GCC TDM-GCC
  • 急问:如何卸掉gcc 3.2庄gcc 2.96
  • 有人遇到过吗,在安装GCC时提示,"checking gcc ...no "
  • gcc编译时出错,gcc: installation problem, cannot exec `as': 没有那个文件或目录!!!求助呀呀!!!!!
  • GCC无法安装的问题,希望有人帮我( Debian 4.04ra无法安装GCC)
  • Solaris8,安装了iconv,gcc和gcclib,然后用gcc编译c程序出错。
  • 一套未安装gcc的Linux中安装gcc rpm包时时出现错误
  • gcc与arm-linux-gcc编译的问题???
  • 下了一个GCC3.0包用tar xjfv gcc-3.0.tar.bz2解压后出现一堆文
  • 请问如何安装rpm格式的gcc如gcc-3.2.2-5.src.rpm,谢谢
  • arm-linux-gcc交叉编译出错,但gcc编译没错,什么原因呢???
  • 在redhat9下,如何将gcc3.x改为gcc2.x?
  • linux x86_64下由于拷贝gcc的lib目录导致gcc编译器出错


  • 站内导航:


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

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

    浙ICP备11055608号-3