2010-05-27 5 views
10

Tengo un archivo que contiene lo siguiente:Ocultación de plantillas ejemplificados en la biblioteca compartida creada con g ++

#include <map> 

class A {}; 

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

Cuando se compila en una biblioteca compartida con g ++, la biblioteca contiene símbolos dinámicos para todos los métodos de std::map<int, A>. Dado que A es privado para este archivo, no hay posibilidad de que std::map se instanciará en cualquier otra biblioteca compartida con los mismos parámetros, por lo que me gustaría ocultar la instanciación de la plantilla (por alguna de las razones descritas en this document).

pensé que debería ser capaz de hacer esto añadiendo una instanciación explícita de la clase de plantilla y marcado como oculto, así:

#include <map> 

class A {}; 
template class __attribute__((visibility ("hidden"))) std::map<int, A>; 

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

Sin embargo, esto no tiene efecto: los símbolos siguen siendo todo exportado. También he intentado que rodea todo el archivo con:

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

pero esto también tiene efecto sobre la visibilidad de los métodos de std::map<int, A> (aunque sí ocultar doSomething). Del mismo modo, compilar con -fvisibility=hidden no tiene ningún efecto sobre la visibilidad de los métodos de std::map<int, A>.

El documento al que he vinculado anteriormente describe el uso de mapas de exportación para restringir la visibilidad, pero eso parece muy tedioso.

¿Hay alguna manera de hacer lo que quiero en g ++ (aparte de usar mapas de exportación)? Si es así, ¿qué es? De lo contrario, ¿hay alguna buena razón por la cual estos símbolos siempre se deben exportar, o es solo una omisión en g ++?

+0

¿Cómo ve estos símbolos? 'nm -g your_lib.so'? Quiero decir que he hecho el mismo experimento y veo que 'doSomething' tiene una etiqueta' T' u oculta cuando digo 'fvisibility = hidden' pero los símbolos de std :: map siempre tienen la etiqueta' W'. Y el documento dice: 'Las definiciones débiles solo juegan un papel en la vinculación estática'. ¿De qué manera estás usando tu biblioteca? –

+0

He estado usando 'readelf -p .dynstr foo.so'. Gracias por señalar que estos son símbolos débiles. Buscar en Google la "plantilla de símbolo débil" ha producido algunos resultados interesantes, como este: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36022, que no entiendo completamente, pero suena como podría estar estrechamente relacionado. – jchl

+0

Mi interpretación del texto en el documento es que el hecho de que el símbolo sea débil solo es relevante para la vinculación estática, no es que los símbolos débiles solo se utilicen para enlaces estáticos. – jchl

Respuesta

10

De informe de error GCC #36022, que era m arked NO VÁLIDA, Benjamin Kosnik comentó:

[A] n clase de excepción que será lanzado entre los DSO debe ser explícitamente marcada con visibilidad predeterminada para que el `type_info' nodos serán unificados entre los DSO. Por lo tanto, la justificación para libstdC++ que tiene espacio de nombres std tiene visibilidad "predeterminado".

También, mirando a través de la libstdc fuente ++ para std::map (mina se encuentra en /usr/include/c++/4.4.4/bits/stl_map.h), parece que la forma libstdC++ hace cumplir visibilidad predeterminada es con la macro _GLIBCXX_BEGIN_NESTED_NAMESPACE que se utiliza en la parte superior de 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) { 

Por lo tanto, su implementación de STL está anulando explícitamente -fvisibility=hidden y #pragma GCC visibility push(hidden)/#pragma GCC visibility pop.

Si realmente quería obligar a los std::map miembros a tener visibilidad oculto entonces creo que se podría utilizar algo como:

// 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` 

A continuación, la siguiente serie de comandos verificará que los std::map<int, A> miembros pueden ser despojados de un objeto compartido:

  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

Tenga en cuenta que antes de la etapa 3, readelf -s libtest.so.1.0 impreso (para mí):

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 [email protected]_3.4 (2) 
    4: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]_1.3 (3) 
    5: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]_3.0 (4) 
    6: 00000000  0 FUNC WEAK DEFAULT UND [email protected]_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 [email protected]@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 [email protected]@CXX 
    80: 00000000  0 FUNC GLOBAL DEFAULT UND _Unwin[email protected]@GCC_3.0 
    81: 00000000  0 FUNC WEAK DEFAULT UND [email protected]@GLIBC_2.1 
    82: 00000d08 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca 
    83: 000007f4  0 FUNC GLOBAL DEFAULT 10 _init 

Y después:

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 [email protected]_3.4 (2) 
    4: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]_1.3 (3) 
    5: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]_3.0 (4) 
    6: 00000000  0 FUNC WEAK DEFAULT UND [email protected]_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 [email protected]@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 [email protected]@CXX 
    47: 00000000  0 FUNC GLOBAL DEFAULT UND [email protected]@GCC_3.0 
    48: 00000000  0 FUNC WEAK DEFAULT UND [email protected]@GLIBC_2.1 
    49: 00000d08 35 FUNC WEAK DEFAULT 12 _ZN9__gnu_cxx13new_alloca 
    50: 000007f4  0 FUNC GLOBAL DEFAULT 10 _init 

Ver también:

+1

Ya había encontrado ese informe de fallos y acababa de consultar los archivos de encabezado C++, pero no se me había ocurrido la idea de volver a definir _GLIBCXX_VISIBILITY_ATTR. Es bastante malo, pero podría intentarlo. Gracias. – jchl

+0

Mi GCC es 4.6, encontré que la macro * _GLIBXX_VISIBILITY_ATTR * se renombró como * _GLIBXX_VISIBILITY *. Y esta macro debe redefinirse como '#define _GLIBCXX_VISIBILITY (V)' en lugar de '#define _GLIBCXX_VISIBILITY (V) __attribute __ ((__ visibility __ (" hidden ")))', de lo contrario puede haber un error de enlace como * referencia indefinida a ' std :: __ throw_bad_alloc() '*. –

0

Negación: No soy un desarrollador de GCC, y por lo tanto esta es una WAG completa (conjetura salvaje culo):

Mi conjetura sería que GCC siempre exporta las definiciones de plantilla, con el fin de permitir que el enlazador para eliminar copias duplicadas de plantillas. Si no se exportó y más de una vez el archivo fuente usó esa plantilla, la fuente completa de la clase std::map<k, v> se duplicará dentro de los dos archivos.

Creo que realmente está prestando más atención a esto de lo que se merece. Las exportaciones son un detalle de implementación en C++. En C, tiene sentido no exportar funciones internas, para que los clientes no confíen en ellas. Pero en C++, las funciones exportadas nunca tienen que tener nada que ver con el código fuente. Una versión de std::map<k, v> de GCC puede ser completamente diferente de otras versiones y, como resultado, los dos binarios no serán compatibles con el enlace.

Si necesita portabilidad, exporte una interfaz C e ignore los detalles de C++ que se exportan. Cualquier cliente de su biblioteca que intente llamar a tales exportaciones o hacer algo con ellos merece bloquearse y grabarse para llamar a detalles obvios de implementación interna.

EDIT: Hecho CW porque no soy 100% positivo.

+1

El motivo por el que quiero ocultar estos símbolos no es para evitar que los usuarios del la biblioteca los llama, pero para reducir el tamaño del archivo .so. Usamos un generador de código que da como resultado bibliotecas con miles de símbolos exportados de este tipo, agregando cientos de kB al tamaño de las tablas de símbolos dinámicos. Reducir el número de símbolos exportados nos ahorrará mucho espacio de disco y memoria, además de mejorar los tiempos de carga y permitir que el compilador genere código más eficiente. – jchl

+0

@jchl: Estás micro-optimizando aquí. No me preocuparía porque cuando se genera un archivo ejecutable esas listas de exportación se eliminarán de todos modos. –

+3

Estoy compilando una biblioteca compartida, no un ejecutable. En la mayoría de los entornos, esto sería una micro-optimización innecesaria, pero debido a nuestra gran cantidad de códigos generados y el uso intensivo de plantillas, esta optimización tiene el potencial de ahorrarnos MB de espacio en disco y RAM, ambos son en demanda. Además, en este punto solo quiero saber por qué no puedo hacer que esto funcione. – jchl

0

¿Tal vez podría usar objcopy con la opción --strip-symbol?

La opción se describe en la objcopy man page

Esto puede resultar tedioso, aunque ...

+0

Esa opción no suena mejor que usar un mapa de exportación.Como este código se genera, lo ideal sería una solución que solo implique modificar el código fuente y no usar herramientas adicionales. – jchl

+0

Oh, no leí tu pregunta tan cuidadosamente como debí. Lo siento ... –

0

En C++, si un argumento de plantilla tiene visibilidad limitada, esta restricción se propaga implícitamente a la instanciación de la plantilla.

#include <map> 

class __attribute__((visibility ("hidden"))) A {}; 

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

debería hacer el trabajo.

- editar -
Una cosa más, `#pragma visibilidad de GCC 'afecta solo a las declaraciones del ámbito de espacio de nombres. miembros de la clase y especializaciones de la plantilla no se ven afectados (Visibility pragmas)

+1

Acabo de probar esto, y lamentablemente no parece haber tenido ningún efecto sobre la visibilidad de la plantilla instanciada. – jchl

+0

Arf tienes razón. Parece que la visibilidad STL se aplica. Esto puede ser útil http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36022. – log0

2

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.

En cuanto a

#undef _GLIBCXX_VISIBILITY_ATTR 

aquí es otra cita:

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.

Cuestiones relacionadas