zoukankan      html  css  js  c++  java
  • 弱符号__attribute__((weak))

    弱符号是什么?

    弱符号:
    若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误。链接器会忽略弱符号,去使用普通的全局符号来解析所有对这些符号的引用,但当普通的全局符号不可用时,链接器会使用弱符号。当有函数或变量名可能被用户覆盖时,该函数或变量名可以声明为一个弱符号。弱符号也称为weak alias(弱别名)。

    attribute((weak))的作用

    情况是这样的,碰到一个棘手的问题:我们不确定外部模块是否提供一个函数func,但是我们不得不用这个函数,即自己模块的代码必须用到func函数:

    extern int func(void);
    ...................
    int a = func();
    if( a > .....)
    {
        ..........
    }
    ............
    

    我们不知道func函数是否被定义了;
    这会导致2个结果:

    1:外部存在这个函数func,并且EXPORT_SYMBOL(func),那么在我自己的模块使用这个函数func,正确。

    2:外部其实不存在这个函数,那么我们使用func,程序直接崩溃。

    所以这个时候,__attribute__((weak)) 派上了用场。

    在自己的模块中定义:

    int  __attribute__((weak))  func(......)
    {
        return 0;
    }
    

    将本模块的func转成弱符号类型,如果遇到强符号类型(即外部模块定义了func),那么我们在本模块执行的func将会是外部模块定义的func。

    如果外部模块没有定义,那么,将会调用这个弱符号,也就是在本地定义的func,直接返回了一个1(返回值视具体情况而定)

    相当于增加了一个默认函数。

    原理:连接器发现同时存在弱符号和强符号,有限选择强符号,如果发现不存在强符号,只存在弱符号,则选择弱符号。如果都不存在:静态链接,恭喜,编译时报错,动态链接:对不起,系统无法启动。

    weak属性只会在静态库(.o .a )中生效,动态库(.so)中不会生效。

    强符号和弱符号的例子

    举个例子:
    strong.c //生成 libstrong.so

    #include <stdio.h>
    void real_func()
    {
    	printf("int real func
    ");
    }
    

    weak.c //生成libweak.so

    #include <stdio.h>
    void real_func() __attribute__((weak));
    void real_func()
    {
    	printf("fake func
    ");
    }
    

    如果

    gcc main.c -lstrong -lweak

    那么输出结果"real func"。

    main.c

    #include <stdio.h>
    extern void real_func();
    void main()
    {
            real_func();
    }
    

    如果

    gcc main.c -lweak -lstrong

    那么输出结果为"fake func"。

    可见,对于动态库,weak属性毫无作用,且main中调用哪个real_func(),取决于顺序。

    如果将strong.c 和 weak.c编译成.a或者.o

    gcc main.c strong.o weak.o

    或者

    gcc main.c strong.o weak.o

    那么输出结果都是"real func"。

    所以,如果在so中使用weak属性,那么任何不符合预期的情况,都是可能出现的。

  • 相关阅读:
    在购物过程中的购买用请求重定向不用转发的原因
    自己在WEB学习过程中遇到的问题
    WEB应用中普通java代码如何读取资源文件
    [课堂总结]C++课堂总结(二)
    [一些问题] ubuntu 18.04下 配置qt opencv的坑
    [学习笔记] Ubuntu下编译C++ OpenCV程序并运行
    [学习笔记] cv2.Canny 边缘检测
    [C++讨论课] 课堂记录(一)
    [R] 简单笔记(一)
    Appium入门示例(Java)
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/9237357.html
Copyright © 2011-2022 走看看