online mac compiler c++ linker g++

c++ - mac - g++ ubuntu



g++ referencia indefinida a typeinfo (14)

Acabo de encontrar el siguiente error (y encontré la solución en línea, pero no está presente en Stack Overflow):

(.gnu.linkonce. [stuff]): referencia indefinida a [method] [object file] :(. gnu.linkonce. [stuff]): referencia no definida a `typeinfo for [classname] ''

¿Por qué uno puede obtener uno de estos errores de enlazador "referencia indefinida a typeinfo"?

(Puntos de bonificación si puede explicar lo que sucede detrás de las escenas).


Acabo de pasar unas horas con este error, y aunque las otras respuestas aquí me ayudaron a entender lo que estaba pasando, no solucionaron mi problema en particular.

Estoy trabajando en un proyecto que compila utilizando tanto clang++ como g++ . No tenía problemas de vinculación con clang++ , pero undefined reference to ''typeinfo for error with g++ .

El punto importante: Vincular orden MATERIAS con g++ . Si enumera las bibliotecas que desea vincular en un orden que es incorrecto, puede obtener el error typeinfo .

Vea esta pregunta SO para obtener más detalles sobre cómo vincular el pedido con gcc / g++ .


Citando del manual de gcc :

Para las clases polimórficas (clases con funciones virtuales), el objeto type_info se escribe junto con el vtable [...] Para todos los demás tipos, escribimos el objeto type_info cuando se usa: al aplicar `typeid ''a una expresión, arrojar un objeto, o referirse a un tipo en una cláusula de captura o especificación de excepción.

Y un poco antes en la misma página:

Si la clase declara funciones virtuales no puras, no en línea, se elige la primera como el "método clave" para la clase, y la variable vtable solo se emite en la unidad de traducción donde se define el método clave.

Entonces, este error ocurre cuando al "método clave" le falta su definición, como otras respuestas ya mencionadas.


De forma similar a la discusión anterior de RTTI, NO-RTTI, este problema también puede ocurrir si usa dynamic_cast y no incluye el código objeto que contiene la implementación de la clase.

Me encontré con este problema sobre la base de Cygwin y luego portar el código a Linux. Los archivos make, la estructura de directorios e incluso las versiones gcc (4.8.2) fueron idénticos en ambos casos, pero el código se vinculó y se ejecutó correctamente en Cygwin, pero no se pudo vincular en Linux. Al parecer, Red Hat Cygwin ha realizado modificaciones de compilador / enlazador que evitan el requisito de vinculación del código objeto.

El mensaje de error del enlazador de Linux me dirigió correctamente a la línea dynamic_cast, pero los mensajes anteriores en este foro me hicieron buscar implementaciones de funciones faltantes en lugar del problema real: código de objeto faltante. Mi solución fue sustituir una función de tipo virtual en la clase base y derivada, por ejemplo, int virtual isSpecialType (), en lugar de usar dynamic_cast. Esta técnica evita el requisito de vincular el código de implementación de objeto solo para que dynamic_cast funcione correctamente.


En la clase base (una clase base abstracta) declaras un destructor virtual y como no puedes declarar un destructor como una función virtual pura, tienes que definirlo aquí mismo en la clase abstracta, solo una definición ficticia como virtual ~ base ( ) {} hará, o en cualquiera de la clase derivada.

Si no lo hace, terminará en un "símbolo indefinido" en el momento del enlace. Dado que VMT tiene una entrada para todas las funciones virtuales puras con un NULL coincidente, ya que actualiza la tabla en función de la implementación en la clase derivada. Pero para las funciones no puras pero virtuales, necesita la definición en el tiempo del enlace para que pueda actualizar la tabla de VMT.

Usa c ++ filt para exigir el símbolo. Al igual que $ c ++ filt _ZTIN10storageapi8BaseHostE generará algo así como "typeinfo for storageapi :: BaseHost".


Encuentro una situación que es rara, pero esto puede ayudar a otros amigos en situaciones similares. Tengo que trabajar en un sistema anterior con gcc 4.4.7. Tengo que compilar código con soporte para c ++ 11 o superior, así que construyo la última versión de gcc 5.3.0. Al construir mi código y vincularlo a las dependencias, si la dependencia se compila con un compilador anterior, obtuve el error de "referencia no definida" aunque definí claramente la ruta de vinculación con -L / ruta / a / lib -llib nombre. Algunos paquetes como boost y proyectos compilados con cmake generalmente tienen una tendencia a usar el compilador anterior, y generalmente causan tales problemas. Tienes que recorrer un largo camino para asegurarte de que usan el compilador más nuevo.


Esto ocurre cuando las funciones virtuales declaradas (no puras) son cuerpos faltantes. En la definición de tu clase, algo así como:

virtual void foo();

Debe definirse (en línea o en un archivo fuente vinculado):

virtual void foo() {}

O declarado puro virtual:

virtual void foo() = 0;


Esto también puede suceder cuando mezclas el -fno-rtti y -frtti . Luego debe asegurarse de que cualquier clase, a la que se type_info en el código -frtti , tenga su método clave compilado con -frtti . Tal acceso puede ocurrir cuando crea un objeto de la clase, usa dynamic_cast etc.

[ source ]


Las respuestas anteriores son correctas, pero este error también puede deberse al intento de usar typeid en un objeto de una clase que no tiene funciones virtuales. C ++ RTTI requiere un vtable, por lo que las clases en las que desea realizar la identificación de tipo requieren al menos una función virtual.

Si desea que la información de tipo funcione en una clase para la que realmente no desea funciones virtuales, haga que el destructor sea virtual.


Posibles soluciones para el código que trata con bibliotecas RTTI y no RTTI:

a) Vuelva a compilar todo con -frtti o -fno-rtti
b) Si a) no es posible para usted, intente lo siguiente:

Supongamos que libfoo está construido sin RTTI. Su código usa libfoo y compila con RTTI. Si usa una clase (Foo) en libfoo que tenga virtuales, es probable que se encuentre con un error de tiempo de enlace que dice: falta typeinfo para la clase Foo.

Defina otra clase (por ejemplo, FooAdapter) que no tenga llamadas virtuales y reenvíe llamadas a Foo que use.

Compila FooAdapter en una pequeña biblioteca estática que no utiliza RTTI y solo depende de los símbolos de libfoo. Proporcione un encabezado y en su lugar use su código (que usa RTTI). Como FooAdapter no tiene función virtual, no tendrá ningún tipo de información y podrás vincular tu binario. Si usa muchas clases diferentes de libfoo, esta solución puede no ser conveniente, pero es un comienzo.


Si está vinculando uno .so con otro, una posibilidad más es compilar con "-fvisibility = hidden" en gcc o g ++. Si ambos archivos .so se construyeron con "-fvisibility = hidden" y el método clave no está en el mismo .so que otra implementación de la función virtual, este último no verá el vtable o typeinfo del primero. Para el enlazador, esto parece una función virtual no implementada (como en las respuestas de paxdiablo y cdleary).

En este caso, debe hacer una excepción para la visibilidad de la clase base con

__attribute__ ((visibility("default")))

en la declaración de clase. Por ejemplo,

class __attribute__ ((visibility("default"))) boom{ virtual void stick(); }

Otra solución, por supuesto, es no usar "-fvisibilidad = oculta". Eso complica las cosas para el compilador y el enlazador, posiblemente en detrimento del rendimiento del código.


Tengo el mismo error cuando mi interfaz (con todas las funciones virtuales puras) necesitaba una función más y olvidé "anularla".

tuve

class ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };

Last vaClose no es virtual, por lo que compilado no sabía dónde obtener la implementación y por lo tanto se confundió. mi mensaje fue:

... TCPClient.o :(. Rodata + 0x38): referencia indefinida a `typeinfo para ICommProvider ''

Cambio simple desde

virtual int vaClose();

a

virtual int vaClose() = 0;

arregló el problema Espero eso ayude


Tengo muchos de estos errores en este momento. Lo que sucedió es que dividí una clase de solo encabezado de archivo en un archivo de encabezado y un archivo cpp. Sin embargo, no actualicé mi sistema de compilación, por lo que el archivo cpp no ​​se compiló. Entre simplemente tener referencias indefinidas a las funciones declaradas en el encabezado pero no implementadas, obtuve muchos de estos errores typeinfo.

La solución fue volver a ejecutar el sistema de compilación para compilar y vincular el nuevo archivo cpp.


Una posible razón es porque está declarando una función virtual sin definirla.

Cuando lo declara sin definirlo en la misma unidad de compilación, está indicando que está definido en otro lugar; esto significa que la fase del enlazador intentará encontrarlo en una de las otras unidades de compilación (o bibliotecas).

Un ejemplo de definición de la función virtual es:

virtual void fn() { /* insert code here */ }

En este caso, está adjuntando una definición a la declaración, lo que significa que el vinculador no necesita resolverlo más tarde.

La línea

virtual void fn();

declara fn() sin definirlo y generará el mensaje de error que usted solicitó.

Es muy similar al código:

extern int i; int *pi = &i;

que indica que el entero i se declara en otra unidad de compilación que debe resolverse en el momento del enlace (de lo contrario, pi no se puede establecer en su dirección).


en mi caso, utilicé una biblioteca de terceros con archivos de encabezado y, por lo tanto, archivo. subclasé una clase y se produjo un error de enlace como este cuando intento crear una instancia de mi subclase.

como lo menciona @sergiy, sabiendo que podría ser el problema de ''rtti'', logré solucionarlo colocando la implementación del constructor en un archivo .cpp separado y aplicando indicadores de compilación ''-fno-rtti'' al archivo . funciona bien.

como todavía no estoy del todo claro sobre el error interno de este enlace, no estoy seguro de si mi solución es general. sin embargo, creo que vale la pena intentarlo antes de probar la forma de adaptador mencionada por @francois. y por supuesto, si todos los códigos fuente están disponibles (no en mi caso), mejor recompile con ''-frtti'' si es posible.

Una cosa más, si eliges probar mi solución, intenta hacer que el archivo separado sea lo más simple posible, y no uses algunas características sofisticadas de C ++. presta especial atención a las cosas relacionadas con el impulso, ya que gran parte depende de rtti.