2014-09-04 113 views
1

如果这个类是多态的,我发现类名不能隐藏在共享库中。例如,我可以在共享库中隐藏或删除类名吗?

// 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; 
} 

我建立一个共享库在Linux上,像这样

$ g++ -fPIC -shared -fvisibility=hidden ../example.cpp -o libexample.so 
$ strip -R .comment -R .note libexample.so 

GCC,那么我打开libexample.so在Emacs的一个正常的文件和搜索,类名BaseChild会找出。

如果我取消注释语句// #define virtual#define virtual,也就是说使BaseChild无虚方法,我发现类名BaseChild不会在共享库中找到。

剂量类名称被存储在类vtable由编译器?或者其他一些原因导致了这个问题?

+1

我相信这可能与名称混搭有关,尽管我不太确定 – 2014-09-04 08:22:11

回答

5

如果这个类是多态的,我发现类名不能隐藏在共享库中。

不清楚你指的是什么样的隐藏。

从链接器符号可见性角度来看,所有具有内部链接的名称都是隐藏的。类没有联系可言,函数和变量做:

$ 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$" 

这些字符串5Child4Base是所属类别返回由typeid()

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编译器开关:

 -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. 
+0

+1我想知道“儿子”的字符串数据在哪里结束? – BeyelerStudios 2014-09-04 08:46:23

+2

@BeyelerStudios'man strings':_GNU字符串打印至少4个字符长的可打印字符序列(或以下选项给出的数字)_。 – 2014-09-04 08:49:53

+0

@MaximYegorushkin非常感谢。我想知道如何打印出typeinfo? – 2014-09-04 08:53:17

相关问题