代码之家  ›  专栏  ›  技术社区  ›  jchl

在用g创建的共享库中隐藏实例化模板++

  •  13
  • jchl  · 技术社区  · 15 年前

    我有一个包含以下内容的文件:

    #include <map>
    
    class A {};
    
    void doSomething() {
       std::map<int, A> m;
    }
    

    std::map<int, A> . 自 A 是这个文件的私有文件,不可能 std::map 将使用相同的参数在任何其他共享库中实例化,因此我想隐藏模板实例化(出于中描述的某些原因) this document

    我想我应该可以通过添加template类的显式实例化并将其标记为隐藏来实现这一点,如下所示:

    #include <map>
    
    class A {};
    template class __attribute__((visibility ("hidden"))) std::map<int, A>;
    
    void doSomething() {
       std::map<int, A> m;
    }
    

    #pragma GCC visibility push(hidden)
    ...
    #pragma GCC visibility pop
    

    但这也不影响这些方法的可见性 (尽管它确实隐藏了 doSomething -fvisibility=hidden 对方法的可见性没有影响 标准::地图<内景,A>

    我上面链接的文档描述了如何使用导出地图来限制可见性,但这似乎非常乏味。

    5 回复  |  直到 15 年前
        1
  •  14
  •   Daniel Trebbien    15 年前

    从GCC错误报告 #36022

    [A] n将在DSO之间抛出的异常类必须是 用默认可见性显式标记,以便“type\u info”节点 在DSO之间统一。 “默认值。”

    另外,查看libstdc++源代码 std::map (我的在 /usr/include/c++/4.4.4/bits/stl_map.h ),libstdc++强制默认可见性的方式似乎是 _GLIBCXX_BEGIN_NESTED_NAMESPACE stl_map.h :

    # define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V)))
    # define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) _GLIBCXX_BEGIN_NAMESPACE(X)
    # define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY_ATTR(default) {
    

    -fvisibility=hidden #pragma GCC visibility push(hidden) #pragma GCC visibility pop .

    如果你真的想强迫 标准::地图 成员具有隐藏的可见性,然后我认为您可以使用以下内容:

    // ensure that default visibility is used with any class that is used as an exception type
    #include <memory>
    #include <new>
    #include <stdexcept>
    
    // now include the definition of `std::map` using hidden visibility
    #include <bits/c++config.h>
    #undef _GLIBCXX_VISIBILITY_ATTR
    #define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden")))
    #include <map>
    #undef _GLIBCXX_VISIBILITY_ATTR
    #define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR`
    

    然后,以下一系列命令将验证 std::map<int, A> 可以从共享对象中剥离成员:

    1. g++ -c -fPIC -fvisibility=hidden test.cpp
    2. g++ -shared -Wl,-soname,libtest.so.1 -o libtest.so.1.0 test.o
    3. strip -x libtest.so.1.0
    4. readelf -s libtest.so.1.0

    注意,在第3步之前, readelf-s libtest.so.1.0版本 印刷品(为我):

    Symbol table '.dynsym' contains 23 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
         2: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
         3: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv@GLIBCXX_3.4 (2)
         4: 00000000     0 FUNC    GLOBAL DEFAULT  UND __gxx_personality_v0@CXXABI_1.3 (3)
         5: 00000000     0 FUNC    GLOBAL DEFAULT  UND _Unwind_Resume@GCC_3.0 (4)
         6: 00000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.1.3 (5)
         7: 00000d02     5 FUNC    WEAK   DEFAULT   12 _ZNSt4pairIKi1AED1Ev
         8: 00000d6c    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEEC1ISt
         9: 00000d96    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        10: 000023bc     0 NOTYPE  GLOBAL DEFAULT  ABS _end
        11: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
        12: 00000d5e     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        13: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
        14: 00000bac     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        15: 00000d08    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        16: 000007f4     0 FUNC    GLOBAL DEFAULT   10 _init
        17: 00000c4a    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
        18: 00000df8     0 FUNC    GLOBAL DEFAULT   13 _fini
        19: 00000dba     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        20: 00000cde    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEED1Ev
        21: 00000d90     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        22: 00000ac6    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
    
    Symbol table '.symtab' contains 84 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 000000f4     0 SECTION LOCAL  DEFAULT    1 
         2: 00000118     0 SECTION LOCAL  DEFAULT    2 
         3: 000001c0     0 SECTION LOCAL  DEFAULT    3 
         4: 0000022c     0 SECTION LOCAL  DEFAULT    4 
         5: 0000039c     0 SECTION LOCAL  DEFAULT    5 
         6: 000006b6     0 SECTION LOCAL  DEFAULT    6 
         7: 000006e4     0 SECTION LOCAL  DEFAULT    7 
         8: 00000754     0 SECTION LOCAL  DEFAULT    8 
         9: 0000077c     0 SECTION LOCAL  DEFAULT    9 
        10: 000007f4     0 SECTION LOCAL  DEFAULT   10 
        11: 00000824     0 SECTION LOCAL  DEFAULT   11 
        12: 00000930     0 SECTION LOCAL  DEFAULT   12 
        13: 00000df8     0 SECTION LOCAL  DEFAULT   13 
        14: 00000e14     0 SECTION LOCAL  DEFAULT   14 
        15: 00000ef8     0 SECTION LOCAL  DEFAULT   15 
        16: 00001240     0 SECTION LOCAL  DEFAULT   16 
        17: 0000225c     0 SECTION LOCAL  DEFAULT   17 
        18: 00002264     0 SECTION LOCAL  DEFAULT   18 
        19: 0000226c     0 SECTION LOCAL  DEFAULT   19 
        20: 00002270     0 SECTION LOCAL  DEFAULT   20 
        21: 00002358     0 SECTION LOCAL  DEFAULT   21 
        22: 00002364     0 SECTION LOCAL  DEFAULT   22 
        23: 000023ac     0 SECTION LOCAL  DEFAULT   23 
        24: 000023b4     0 SECTION LOCAL  DEFAULT   24 
        25: 00000000     0 SECTION LOCAL  DEFAULT   25 
        26: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
        27: 0000225c     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_LIST__
        28: 00002264     0 OBJECT  LOCAL  DEFAULT   18 __DTOR_LIST__
        29: 0000226c     0 OBJECT  LOCAL  DEFAULT   19 __JCR_LIST__
        30: 00000930     0 FUNC    LOCAL  DEFAULT   12 __do_global_dtors_aux
        31: 000023b4     1 OBJECT  LOCAL  DEFAULT   24 completed.5942
        32: 000023b8     4 OBJECT  LOCAL  DEFAULT   24 dtor_idx.5944
        33: 000009b0     0 FUNC    LOCAL  DEFAULT   12 frame_dummy
        34: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
        35: 00002260     0 OBJECT  LOCAL  DEFAULT   17 __CTOR_END__
        36: 0000123c     0 OBJECT  LOCAL  DEFAULT   15 __FRAME_END__
        37: 0000226c     0 OBJECT  LOCAL  DEFAULT   19 __JCR_END__
        38: 00000dc0     0 FUNC    LOCAL  DEFAULT   12 __do_global_ctors_aux
        39: 00000000     0 FILE    LOCAL  DEFAULT  ABS test.cpp
        40: 00000d64     8 FUNC    LOCAL  HIDDEN   12 _ZNKSt8_Rb_treeIiSt4pairI
        41: 000023b0     4 OBJECT  LOCAL  HIDDEN   23 DW.ref.__gxx_personality_
        42: 00000b40    11 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        43: 00000bc8   129 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        44: 00000bb1    11 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        45: 00000b4c    96 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        46: 00000ca0    62 FUNC    LOCAL  HIDDEN   12 _ZNKSt8_Rb_treeIiSt4pairI
        47: 00000ab2    19 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        48: 00002364     0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
        49: 00000a56    92 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        50: 000009ec    30 FUNC    LOCAL  HIDDEN   12 _Z11doSomethingv
        51: 00000c6e    49 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        52: 00000a32    35 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        53: 000023ac     0 OBJECT  LOCAL  HIDDEN   23 __dso_handle
        54: 00000a0a    19 FUNC    LOCAL  HIDDEN   12 _ZNSt3mapIi1ASt4lessIiESa
        55: 00002268     0 OBJECT  LOCAL  HIDDEN   18 __DTOR_END__
        56: 00000bbc    11 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        57: 00000a1e    19 FUNC    LOCAL  HIDDEN   12 _ZNSt3mapIi1ASt4lessIiESa
        58: 00000d2c    50 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        59: 00000aea    85 FUNC    LOCAL  HIDDEN   12 _ZNSt8_Rb_treeIiSt4pairIK
        60: 000009e7     0 FUNC    LOCAL  HIDDEN   12 __i686.get_pc_thunk.bx
        61: 00002270     0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
        62: 00000d02     5 FUNC    WEAK   DEFAULT   12 _ZNSt4pairIKi1AED1Ev
        63: 00000c4a    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
        64: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
        65: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
        66: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv@@GLIBCXX_3.4
        67: 00000df8     0 FUNC    GLOBAL DEFAULT   13 _fini
        68: 00000d6c    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEEC1ISt
        69: 00000dba     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        70: 00000cde    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEED1Ev
        71: 00000d5e     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        72: 00000d90     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        73: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
        74: 00000d96    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        75: 00000bac     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        76: 000023bc     0 NOTYPE  GLOBAL DEFAULT  ABS _end
        77: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
        78: 00000ac6    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
        79: 00000000     0 FUNC    GLOBAL DEFAULT  UND __gxx_personality_v0@@CXX
        80: 00000000     0 FUNC    GLOBAL DEFAULT  UND _Unwind_Resume@@GCC_3.0
        81: 00000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@GLIBC_2.1
        82: 00000d08    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        83: 000007f4     0 FUNC    GLOBAL DEFAULT   10 _init
    

    之后:

    Symbol table '.dynsym' contains 23 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
         2: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
         3: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv@GLIBCXX_3.4 (2)
         4: 00000000     0 FUNC    GLOBAL DEFAULT  UND __gxx_personality_v0@CXXABI_1.3 (3)
         5: 00000000     0 FUNC    GLOBAL DEFAULT  UND _Unwind_Resume@GCC_3.0 (4)
         6: 00000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.1.3 (5)
         7: 00000d02     5 FUNC    WEAK   DEFAULT   12 _ZNSt4pairIKi1AED1Ev
         8: 00000d6c    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEEC1ISt
         9: 00000d96    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        10: 000023bc     0 NOTYPE  GLOBAL DEFAULT  ABS _end
        11: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
        12: 00000d5e     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        13: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
        14: 00000bac     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        15: 00000d08    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        16: 000007f4     0 FUNC    GLOBAL DEFAULT   10 _init
        17: 00000c4a    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
        18: 00000df8     0 FUNC    GLOBAL DEFAULT   13 _fini
        19: 00000dba     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        20: 00000cde    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEED1Ev
        21: 00000d90     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        22: 00000ac6    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
    
    Symbol table '.symtab' contains 51 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 000000f4     0 SECTION LOCAL  DEFAULT    1 
         2: 00000118     0 SECTION LOCAL  DEFAULT    2 
         3: 000001c0     0 SECTION LOCAL  DEFAULT    3 
         4: 0000022c     0 SECTION LOCAL  DEFAULT    4 
         5: 0000039c     0 SECTION LOCAL  DEFAULT    5 
         6: 000006b6     0 SECTION LOCAL  DEFAULT    6 
         7: 000006e4     0 SECTION LOCAL  DEFAULT    7 
         8: 00000754     0 SECTION LOCAL  DEFAULT    8 
         9: 0000077c     0 SECTION LOCAL  DEFAULT    9 
        10: 000007f4     0 SECTION LOCAL  DEFAULT   10 
        11: 00000824     0 SECTION LOCAL  DEFAULT   11 
        12: 00000930     0 SECTION LOCAL  DEFAULT   12 
        13: 00000df8     0 SECTION LOCAL  DEFAULT   13 
        14: 00000e14     0 SECTION LOCAL  DEFAULT   14 
        15: 00000ef8     0 SECTION LOCAL  DEFAULT   15 
        16: 00001240     0 SECTION LOCAL  DEFAULT   16 
        17: 0000225c     0 SECTION LOCAL  DEFAULT   17 
        18: 00002264     0 SECTION LOCAL  DEFAULT   18 
        19: 0000226c     0 SECTION LOCAL  DEFAULT   19 
        20: 00002270     0 SECTION LOCAL  DEFAULT   20 
        21: 00002358     0 SECTION LOCAL  DEFAULT   21 
        22: 00002364     0 SECTION LOCAL  DEFAULT   22 
        23: 000023ac     0 SECTION LOCAL  DEFAULT   23 
        24: 000023b4     0 SECTION LOCAL  DEFAULT   24 
        25: 00000000     0 SECTION LOCAL  DEFAULT   25 
        26: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
        27: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
        28: 00000000     0 FILE    LOCAL  DEFAULT  ABS test.cpp
        29: 00000d02     5 FUNC    WEAK   DEFAULT   12 _ZNSt4pairIKi1AED1Ev
        30: 00000c4a    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
        31: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
        32: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
        33: 00000000     0 FUNC    GLOBAL DEFAULT  UND _ZdlPv@@GLIBCXX_3.4
        34: 00000df8     0 FUNC    GLOBAL DEFAULT   13 _fini
        35: 00000d6c    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEEC1ISt
        36: 00000dba     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        37: 00000cde    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt4pairIKi1AEED1Ev
        38: 00000d5e     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        39: 00000d90     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        40: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
        41: 00000d96    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        42: 00000bac     5 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        43: 000023bc     0 NOTYPE  GLOBAL DEFAULT  ABS _end
        44: 000023b4     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
        45: 00000ac6    35 FUNC    WEAK   DEFAULT   12 _ZNSaISt13_Rb_tree_nodeIS
        46: 00000000     0 FUNC    GLOBAL DEFAULT  UND __gxx_personality_v0@@CXX
        47: 00000000     0 FUNC    GLOBAL DEFAULT  UND _Unwind_Resume@@GCC_3.0
        48: 00000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@GLIBC_2.1
        49: 00000d08    35 FUNC    WEAK   DEFAULT   12 _ZN9__gnu_cxx13new_alloca
        50: 000007f4     0 FUNC    GLOBAL DEFAULT   10 _init
    

        2
  •  2
  •   user184968 user184968    15 年前

    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36022 : The std::namespace is supposed to be exposed and is marked as such in the libstdc++ headers.

    至于

    #undef _GLIBCXX_VISIBILITY_ATTR
    

    下面是另一句话:

    If you were to hack in support for allowing namespace std to have hidden visibility, and run the testsuite with -fvisibility=hidden (see attached patch) you would notice the breakdown in testresults, with mass failures.

        3
  •  0
  •   Billy ONeal    15 年前

    免责声明 :我不是一个GCC开发人员,因此这是一个完整的WAG(野驴猜测):

    我猜GCC总是导出模板定义,以便允许链接器删除模板的重复副本。如果没有导出,并且源文件多次使用该模板,则 std::map<k, v> 类将在两个文件中复制。

    我觉得你对这件事的关注度太高了。导出是C++中的实现细节。在C语言中,不导出内部函数是有意义的,这样客户机就不会依赖它们。但是在C++中,导出的函数永远不必与源代码有任何关系。GCC的一个版本 标准::地图<k、 v> 可能与其他版本完全不同,因此这两个二进制文件将无法链接兼容。

    如果您绝对需要移植性,导出C接口,忽略导出的C++细节。库中任何试图调用此类导出或对其执行任何操作的客户机都应该因为调用明显的内部实现细节而崩溃并烧掉。

    编辑:因为我不是100%阳性。

        4
  •  0
  •   S.C. Madsen    15 年前

    也许可以将objcopy与--strip symbol选项一起使用?

    在objcopy中描述了该选项 man page

    但这可能会很乏味。。。

        5
  •  0
  •   log0    15 年前

    #include <map>
    
    class __attribute__((visibility ("hidden"))) A {};
    
    void doSomething() {
      std::map<int, A> m;
    }
    

    我应该做这项工作。

    --编辑--
    还有一件事,“pragma GCC visibility”只影响命名空间范围声明。类成员和模板专门化不受影响( Visibility pragmas