我可以隐藏或删除共享库中的类名吗
Can I hide or remove the class name in the shared library?
我发现如果这个类是多态的,那么类名就不能隐藏在共享库中。例如,
// example.cpp
#include <stdio.h>
#include <string.h>
// #define virtual
class Base
{
public:
virtual const char* whatiam()
{
return "Papa";
}
};
class Child : public Base
{
public:
virtual const char* whatiam()
{
return "Son";
}
};
const char* whatiam(Base* obj)
{
return obj->whatiam();
}
__attribute__((visibility("default"))) const char* TheAPI(int n)
{
static char buf[64];
Child t;
sprintf(buf, "I'm %s.", whatiam(&t));
return buf;
}
我用gcc在Linux上构建了一个共享库,比如这个
$ g++ -fPIC -shared -fvisibility=hidden ../example.cpp -o libexample.so
$ strip -R .comment -R .note libexample.so
然后我在Emacs中将libexample.so
作为一个普通文件打开并搜索,会找到类名Base
和Child
。
如果我将语句// #define virtual
取消注释为#define virtual
,也就是说使Base
和Child
没有虚拟方法,我会发现在共享库中找不到类名Base
和Child
。
编译器是否将类名存储在类vtable中?还是其他原因导致了这个问题?
我发现如果这个类是多态的,那么这个类名就不能隐藏在共享库中。
不清楚你指的是什么样的隐藏。
从链接器符号可见性的角度来看,所有具有内部链接的名称都是隐藏的。类根本没有链接,函数和变量有:
$ nm -C libexample.so
nm: libexample.so: no symbols
$ nm -D -C libexample.so
0000000000201030 B __bss_start
w __cxa_finalize
0000000000201030 D _edata
00000000002010a0 B _end
0000000000000944 T _fini
w __gmon_start__
0000000000000728 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
U sprintf
0000000000000899 T TheAPI(int)
U vtable for __cxxabiv1::__class_type_info
U vtable for __cxxabiv1::__si_class_type_info
$ strings libexample.so | c++filt
__gmon_start__
_init
_fini
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
__cxa_finalize
_Jv_RegisterClasses
TheAPI(int)
sprintf
vtable for __cxxabiv1::__si_class_type_info
vtable for __cxxabiv1::__class_type_info
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6
_edata
__bss_start
_end
CXXABI_1.3
GLIBC_2.2.5
fffff.
Papa
I'm %s.
5Child
4Base
;*3$"
这些字符串5Child
和4Base
是typeid()
:返回的typeinfo
typeinfo name for Child:
.string "5Child"
.hidden typeinfo for Child
.weak typeinfo for Child
.section .data.rel.ro._ZTI5Child,"awG",@progbits,typeinfo for Child,comdat
.align 16
.type typeinfo for Child, @object
.size typeinfo for Child, 24
typeinfo name for Base:
.string "4Base"
.hidden typeinfo for Base
.weak typeinfo for Base
.section .data.rel.ro._ZTI4Base,"awG",@progbits,typeinfo for Base,comdat
.align 16
.type typeinfo for Base, @object
.size typeinfo for Base, 16
您可以使用-fno-rtti
编译器开关禁用typeinfo:
-fno-rtti
Disable generation of information about every class with virtual
functions for use by the C++ run-time type identification features
(dynamic_cast and typeid). If you don't use those parts of the
language, you can save some space by using this flag. Note that
exception handling uses the same information, but G++ generates it
as needed. The dynamic_cast operator can still be used for casts
that do not require run-time type information, i.e. casts to "void
*" or to unambiguous base classes.
相关文章:
- 将数组的地址分配给变量并删除
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C/C++编译器通常会删除重复的库吗
- 从链接列表c++中删除一个项目
- C++如何通过用户输入删除列表元素
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 使用函数"remove"删除重复元素
- 隐藏、显示、添加或删除功能区中的按钮?
- 删除的操作员隐藏了类操作员
- 隐藏和删除Admob横幅
- 隐藏或删除不需要的字符串从 Windows 可执行文件版本中
- 我可以隐藏或删除共享库中的类名吗
- 删除/隐藏QAT
- 在wxWidgets c++中是否可以隐藏/删除最大化按钮?
- 检测和删除一个网格的隐藏表面
- 如何从文件名向量中删除隐藏文件
- 从记忆中找到和删除隐藏纹理的最佳方法