Gcc中__attribute__关键字之visibility属性

Gcc中__attribute__关键字之visibility属性

    visibility用于设置动态链接库中函数的可见性,将变量或函数设置为hidden,则该符号仅在本so中可见,在其他库中则不可见。

    g++在编译时,可用参数-fvisibility指定所有符号的可见性(不加此参数时默认外部可见,参考man g++中-fvisibility部分);若需要对特定函数的可见性进行设置,需在代码中使用__attribute__设置visibility属性。

    编写大型程序时,可用-fvisibility=hidden设置符号默认隐藏,针对特定变量和函数,在代码中使用__attribute__ ((visibility("default")))另该符号外部可见,这种方法可用有效避免so之间的符号冲突。

    下面是visibility的实例,这里extern “C”可以省略(另外两篇文章gcc __attribute__关键字举例之alias C++覆盖系统函数的方法 中extern "C"不可用省略)。

    值得注意的是,visibility2.cc中可以调用fun1,原因是visibility1.o和visibility2.o同属于一个so文件。 

  visibility1.cc:

1

2

3

4

5

6

#include <stdio.h> 

extern "C" void fun1() 

  printf("in %s\n",__FUNCTION__); 

__attribute__ ((visibility("hidden"))) void fun1();//若编译此文件时使用了参数-fvisibility=hidden,则此行可以省略

 visibility2.cc:

1

2

3

4

5

6

7

8

#include <stdio.h> 

extern "C" void fun1(); 

extern "C" void fun2() 

  fun1(); 

  printf("in %s\n",__FUNCTION__); 

__attribute__ ((visibility("default"))) void fun2();//若编译此文件时没有使用参数-fvisibility或设置参数-fvisibility=default,则此行可以省略

main.cc:

1

2

3

4

5

6

7

8

extern "C" void fun1(); 

extern "C" void fun2(); 

int main() 

  fun1(); 

  fun2(); 

  return 0; 

}

Makefile:

1

2

3

4

5

6

7

8

9

10

11

12

13

all:test 

test:main.o libvisibility.so 

        g++ -o test main.o -lvisibility -L . 

main.o::main.cc 

        g++ -c main.cc 

libvisibility.so:visibility1.o visibility2.o 

        g++ -shared -o libvisibility.so visibility1.o visibility2.o 

visibility1.o:visibility1.cc 

        g++ -fvisibility=hidden -fPIC -c visibility1.cc 

visibility2.o:visibility2.cc 

        g++ -fvisibility=hidden -fPIC -c visibility2.cc 

clean: 

        rm -f *.o *.so test

编译和输出:

1

2

3

4

5

6

7

8

9

10

$ make 

g++ -c main.cc 

g++ -fvisibility=hidden -fPIC -c visibility1.cc 

g++ -fvisibility=hidden -fPIC -c visibility2.cc 

g++ -shared -o libvisibility.so visibility1.o visibility2.o 

g++ -o test main.o -lvisibility -L . 

main.o: In function `main': 

main.cc:(.text+0x5): undefined reference to `fun1' 

collect2: ld returned 1 exit status 

make: *** [test] Error 1

可以看到,main()中可以不可用调用fun1,可以调用fun2,因为fun1已经设置为外部不可见,fun2设置为外部可见。

使用readelf对各个.o文件分析可以看到,fun1的Vis属性为HIDDEN,fun2的Vis属性为DEFAULT:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

$ readelf -s visibility1.o|grep fun 

     6: 0000000000000007     5 OBJECT  LOCAL  DEFAULT    6 _ZZ4fun1E12__FUNCTION__ 

    12: 0000000000000000    30 FUNC    GLOBAL HIDDEN    2 fun1 

   

$ readelf -s visibility2.o|grep fun 

     6: 0000000000000007     5 OBJECT  LOCAL  DEFAULT    6 _ZZ4fun2E12__FUNCTION__ 

    12: 0000000000000000    35 FUNC    GLOBAL DEFAULT    2 fun2 

    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND fun1 

   

$ readelf -s libvisibility.so|grep fun 

     9: 00000000000006ac    35 FUNC    GLOBAL DEFAULT   12 fun2 

    41: 000000000000071d     5 OBJECT  LOCAL  DEFAULT   14 _ZZ4fun1E12__FUNCTION__ 

    43: 0000000000000729     5 OBJECT  LOCAL  DEFAULT   14 _ZZ4fun2E12__FUNCTION__ 

    48: 000000000000068c    30 FUNC    LOCAL  HIDDEN   12 fun1 

    54: 00000000000006ac    35 FUNC    GLOBAL DEFAULT   12 fun2

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gcc支持很多用于优化的属性(__attribute__),以下是其一些常见的: 1. `__attribute__((pure))`: 声明函数没有任何副作用,即函数只依赖于它的输入参数,不会修改任何全局变量或静态变量。 2. `__attribute__((const))`: 声明函数没有任何副作用,并且函数的返回值只依赖于它的输入参数,不会受任何全局变量或静态变量的影响。 3. `__attribute__((noreturn))`: 声明函数不会返回,例如在函数内部调用了exit(),abort()等函数。 4. `__attribute__((deprecated))`: 声明函数或变量已经被弃用,不推荐使用。 5. `__attribute__((aligned(n)))`: 声明变量的内存对齐方式,n表示对齐字节数。 6. `__attribute__((optimize("O0/O1/O2/O3")))`: 声明函数的优化级别,O0表示不优化,O1表示优化速度,O2表示平衡性能和大小,O3表示优化大小。 7. `__attribute__((packed))`: 声明结构体或联合体的内存对齐方式为紧凑模式,即不填充字节。 8. `__attribute__((visibility("default/hidden/internal")))`: 声明符号的可见性,default表示符号可见,hidden表示符号不可见,internal表示符号只在当前模块内可见。 9. `__attribute__((format(printf, x, y)))`: 声明函数参数的格式化输出方式,x表示参数从第几个开始,y表示参数的总数。 10. `__attribute__((unused))`: 声明变量或函数未被使用,但是不产生警告。 以上是一些常见的gcc支持的优化属性(__attribute__),还有其他更多的属性可以根据需要使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值