2014-09-04 85 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

相關問題