简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:理解C/C++中,[[clang::lto_visibility_public]]的用法。
class [[clang::lto_visibility_public]] IBinder : public virtual RefBase{};
在IBinder.h中,发现IBinder前边的写法很奇怪,科普下它的作用。
[[clang::lto_visibility_public]]作用:
在C++中,[[clang::lto_visibility_public]]的作用是在链接时优化(LTO)期间指定一个符号应具有公共可见性。
它确保在执行LTO时,链接器不会消除或优化掉该符号。
clang还有其他属性,比如:
- [[clang::lto_visibility_private]]:用于指定符号在LTO期间应具有私有可见性,确保链接器在LTO期间不会消除或优化该符号。
- [[clang::lto_visibility_protected]]:用于指定符号在LTO期间应具有受保护的可见性,确保链接器在LTO期间不会消除或优化该符号。
- [[clang::lto_visibility_hidden]]:用于指定符号在LTO期间应具有隐藏的可见性,确保链接器在LTO期间不会消除或优化该符号。
2.应用实例
<1>v1.0
#include <iostream>
using namespace std;
//[[clang::lto_visibility_public]] void foo() {
//[[clang::lto_visibility_hidden]] void foo() {
//[[clang::lto_visibility_protected]] void foo() {
[[clang::lto_visibility_private]] void foo() {
printf("xxx---------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
int main() {
foo();
return 0;
}
<2>v2.0
1.clang_visitable_02.h
#include <iostream>
[[clang::lto_visibility_private]] void privateFunction();
[[clang::lto_visibility_protected]] void protectedFunction();
[[clang::lto_visibility_hidden]] void hiddenFunction();
[[clang::lto_visibility_public]] void publicFunction();
2.clang_visitable_02.cpp
// - [[clang::lto_visibility_private]]将符号的可见性限制为仅在当前编译单元中可见。
// - [[clang::lto_visibility_protected]]将符号的可见性限制为当前编译单元和其他使用相同链接时可见的编译单元。
// - [[clang::lto_visibility_hidden]]将符号的可见性限制为当前编译单元和其他使用相同链接时可见的编译单元,但不会导出符号。
// - [[clang::lto_visibility_public]]将符号的可见性设置为全局可见,可以在任何编译单元中访问。
#include <iostream>
#include "clang_visitable_02.h"
[[clang::lto_visibility_private]] void privateFunction() {
printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
[[clang::lto_visibility_protected]] void protectedFunction() {
printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
[[clang::lto_visibility_hidden]] void hiddenFunction() {
printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
c void publicFunction() {
printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
3.main.cpp
#include "clang_visitable_02.h"
int main() {
privateFunction();
protectedFunction();
hiddenFunction();
publicFunction();
return 0;
}
<3>.编译实验
1.clang++编译选项
1.-fvisibility=hidden: 表示所有符号默认都是不可见的,除非明确标记为可见.
# clang++ -fPIC -shared -o libtest.so -fvisibility=hidden -flto clang_visitable_02.cpp
2.-fvisibility=default:这是默认值,表示所有符号都是可见的.
# clang++ -fPIC -shared -o libtest.so -fvisibility=default -flto clang_visitable_02.cpp
4.-fvisibility=protected:表示所有符号默认都是受保护的,除非明确标记为可见.
# clang++ -fPIC -shared -o libtest.so -fvisibility=protected -flto clang_visitable_02.cpp
2.执行程序
# clang++ main.cpp -L ./ -ltest -o main
# export LD_LIBRARY_PATH=.
# ./main
3.总结
<1>.结论一
发现编译:-fvisibility=hidden、default、protected选项都不会对程序运行造成影响,在-fvisibility=hidden选项的情况下函数都不可被main函数调用,在default、protected选项都可用。
<2>.结论二:IBinder增加[[clang::lto_visibility_public]]的原因
clang 优化中的“ -fwhole-program-vtables ”选项会导致IBinder出现问题。在SurfaceFlinger中,优化使BpBinder对象的行为类似于IBinder,当调用linkToDeath的时候会出问题,应该调用BpBinder的linkToDeath函数,现在却调用了IBinder的linkToDeath函数。当用“ [[clang :: lto_visibility_public]] ”为clang注释IBinder时,将调用适当的linkToDeath函数。
大家可以做实验试下,-fwhole-program-vtables -flto命令如下:
# clang++ -fPIC -shared -o libtest.so -fwhole-program-vtables -flto clang_visitable_02.cpp
<3>.结论三
如果想要控制libtest.so中的函数是否能被访问,举个简单的例子
(1).test.cpp:被编译成libtest.so
void hiddenFunction() {
printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
__attribute ((visibility("default"))) void publicFunction() {
printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
}
(2).编译
# clang++ -fPIC -shared -o libtest.so -fvisibility=hidden -flto test.cpp
# clang++ main.cpp -L ./ -ltest -o main
(3). 实验结论
在执行clang++ main.cpp -L ./ -ltest -o main命令,也就是main函数连接libtest.so库时,会 报错,原因是说没有定义hiddenFunction函数,为什么呢?因为它没有显示定义__attribute ((visibility(“default”))) ,它可以在编译-fvisibility=hidden -flto函数不被外界找到,但是定义__attribute ((visibility(“default”)))后,外界仍然可以找到它。
它其实和GNU C的访问情况是一样的,只不过这个使用clang++编译,具体可以参考另一篇文章: C语言之__attribute__((visibility(“default“)))等gcc flag讲解(六十二)
4.最终结论
<1>. [[clang::lto_visibility_public]]修饰不影响函数是否被隐藏
<2>. 函数是否被隐藏,取决于编译选项命令和函数内部定义。
例如:
1.是否使用 clang++ -fvisibility=hidden -flto编译选项
2.是否在函数中增加如下函数的修饰
__attribute ((visibility("default"))) void publicFunction() {
}