• gcc编译器遇到的部分问题的总结(二)


    继续上次的接着写,还有一种常见的错误,也是undefined reference to symbol XXX,但是底下会加上一句:note: 'XXX' is defined in DSO xxx.so so try adding it to the linker command line,当然,这个问题本质上也是一个找不到符号的问题,我们通过再链接参数上增加该库名的问题也能解决这个问题,但是这个错误多出了这一条提示,毕竟与通常的符号未找到有些区别的,下面我们通过一个例子来分析这个问题。

    foo1.c
    
    #include <stdio.h>
    extern int bar (); 
    int main ()
    {
        printf ("%d
    ", bar ());
    }
    foo2.c
    
    extern int foo (); 
    int bar () { return foo (); }
    foo3.c
    
    int foo () { return 0; }

    以上是三个很简单的C程序源文件,foo3.c中有一个函数foo(),foo2.c中定义了一个函数bar(),其中调用了函数foo(),foo1.c是主程序,调用bar()函数。直接编译当然没问题,按照上篇讲的,按照调用顺序编译gcc foo1.c foo2.c foo3.c -o foo,没有任何问题。下面我们尝试将其中的一些函数编译成动态链接库。

    gcc -c foo1.c foo2.c foo3.c -fPIC

    gcc -o foo3.so foo3.o -shared

    gcc -o foo2.so foo2.o foo3.so -shared

    gcc -o foo foo1.o foo2.so

    没有任何问题,程序正常执行。

    接着我们将foo1.c稍作修改:

    foo1.c
    
    #include <stdio.h>
    extern int bar (); 
    extern int foo (); 
    int main ()
    {
        printf ("%d
    ", bar ());
        foo();
    }

    我们在main()函数中增加了直接对foo3.c中的foo()函数的调用。下面重新编译foo1.c

    出现这个问题了,链接器说找不到符号foo,当然了,我们知道,foo函数在foo3.so中,我们编译命令里没加上foo3.so,当然找不到,加上foo3.so,依然能成功编译。

    但是这个note是为什么呢。其实也不难明白,因为我们的foo2.so中也调用了这个foo这个函数,而且我们在编译foo2.so的时候已经将foo3.so作为foo2.so的一个NEEDED项。可以使用readelf -d foo2.so命令查看下:

    因此,编译器给你个提示,我虽然没找到foo这个符号(所以要报错undefined reference to symbol),但是可以提示你一下,你其他的DSO(dynamic shared object)中用到过这个符号。那么该如何利用foo2.so中添加过的这个foo函数的符号来解决这个链接问题呢,很简单,告诉链接器,直接把foo2.so中需要用到的东西(带NEEDED标识的)原样copy到主程序中就可以啦,那么,foo2.so中用过的so库,主程序在链接时就不用再写一遍啦。告诉链接器的参数就是--copy-dt-needed-entries。gcc命令中直接写的时候前面要加上"-Wl,"参数,告知编译器后面的参数不是编译器参数,而是链接器参数。

     

    成功编译运行!

  • 相关阅读:
    [洛谷P4585] [FJOI2015] 火星商店问题
    [bzoj4311] 向量
    [bzoj4977] [Lydsy1708月赛] 跳伞求生
    sdut-1153 C语言实验——求两个整数之中较大者
    sdut_1116
    sdut_1189
    汉诺塔
    二分查找
    类似二分查找算法
    [YTU]_2922(Shape系列-8)
  • 原文地址:https://www.cnblogs.com/yutongqing/p/6888013.html
Copyright © 2020-2023  润新知