El vinculador de C ++ Builder le advertirá cuando mezcle archivos de objetos vinculados con clásico y clang juntos, lo que le ayudará a evitar errores de vinculador o tiempo de ejecución.
Hoy, en 2020, recomendamos usar los compiladores de Clang modernos, especialmente con el trabajo que hemos estado haciendo para Win64 (por ejemplo, un depurador completamente nuevo) y las mejoras de RTL para facilitar la actualización desde el clásico. Sin embargo, muchos clientes actualizan en pasos: primero desde el clásico Win32 a Clang Win32, y luego agregando Win64 después. De hecho, a menudo recomendamos directamente esto como una estrategia de actualización, para pasar a Clang primero y después a Win64, en dos pasos.
Sin embargo, existe un problema común al pasar de los compiladores clásicos a los compiladores clang. Los archivos de objetos (bibliotecas .obj y .lib) generados por los compiladores clásico y Clang Win32 no son compatibles binarios entre sí. (Tanto el clásico como el clang pueden vincularse con Delphi, pero el clásico y el clang no pueden vincularse entre sí). Si intentas crear una aplicación en la que algunas partes se compilen con Clang y otras con clásico, todas mezcladas, puedes esperar cualquier cosa de los errores del vinculador. a la inestabilidad del tiempo de ejecución. Sin embargo, es fácil de hacer accidentalmente, tanto al actualizar como al agregar una nueva biblioteca o EXE a su proyecto.
En 10.3.3, y esto se documentó en la ayuda en línea pero no se escribió en el blog en ese momento, agregamos una nueva advertencia de vinculador para ayudarlo a detectar estas situaciones.
Antes de mostrar la solución, echemos un vistazo rápido a lo que puede suceder si tiene este error en sus compilaciones.
Table of Contents
Problemas cuando los compiladores no coinciden
En 10.3.3 y versiones posteriores, recibirá una advertencia del vinculador (consulte a continuación) antes de cualquiera de las siguientes. Pero si está utilizando una versión anterior, antes de agregar la advertencia que diagnostica el problema, es posible que vea solo los siguientes errores. Aparecen al vincular la aplicación.
Errores de tiempo de enlace
Cuando una aplicación creada con la cadena de herramientas de Clang está vinculada a una biblioteca compilada por Classic, es posible que vea los siguientes errores:
1 2 3 |
[ilink32 Error] Error: Unresolved external '__InitExceptBlockLDTC' [ilink32 Error] Error: Unresolved external '_ThrowExceptionLDTC' Error: Unresolved external '_CatchCleanup()' |
Cuando una aplicación creada con la cadena de herramientas Classic está vinculada a una biblioteca creada por Clang, es posible que vea los siguientes errores:
1 2 3 4 5 6 7 8 9 |
Error: Unresolved external '___seh_personality_v0' Error: Unresolved external '__Unwind_SjLj_Register' Error: Unresolved external 'std::_Xbad_alloc()' Error: Unresolved external '___cxa_begin_catch' Error: Unresolved external '___cxa_rethrow' Error: Unresolved external '___cxa_end_catch' Error: Unresolved external '__Unwind_SjLj_Unregister' Error: Unresolved external '__Unwind_Resume' Error: Unresolved external '___cpp_terminate' |
Errores en tiempo de ejecución
En algunos casos, es posible que no vea ningún error del vinculador y ejecutará su aplicación. Lo más probable es que en algún momento su aplicación se bloquee y será difícil averiguar por qué, porque el código se ve bien. En realidad, será debido a que dos compiladores diferentes hacen las cosas de diferentes maneras: diferente distribución de memoria, alineación, expectativas de la biblioteca en tiempo de ejecución, manejo de excepciones, todo tipo de posibles diferencias.
No es una buena situación tener errores extraños en el enlazador o un comportamiento extraño en tiempo de ejecución. Así que agregamos una advertencia para verificar esta situación.
Diagnóstico: una nueva advertencia de vinculador
RAD Studio / C ++ Builder 10.3.3 y más reciente le advierte acerca de mezclar clang y clásico al vincular. (Si se producen errores del vinculador como el anterior, esta advertencia se emite antes que ellos, por lo que verá la advertencia antes de cualquier error debido al problema).
El mensaje dice “Advertencia: no coincide el compilador”. y luego le dice lo que esperaba y lo que encontró:
1 |
Warning: Compiler mismatch. Module 'Z:RAD STUDIO PROJECTSDEMOS AND WEBINARSMIXING CLASSIC AND CLANGWIN32DEBUGMYSTATICLIB.LIB|Unit1' built with bcc32 compiler; expected the bcc32c compiler because of 'Z:RAD STUDIO PROJECTSDEMOS AND WEBINARSMIXING CLASSIC AND CLANGWIN32DEBUGVCLAPP.OBJ' |
Entonces, ¿cómo comprueba el vinculador los objetos mixtos y cómo sabe qué esperar?
En el error anterior, tengo una aplicación VCL que se vincula en una biblioteca estática. La aplicación VCL está construida con Clang. La biblioteca está construida con clásicos. La aplicación clang se vincula en la biblioteca con:
1 |
#pragma comment(lib, "MyStaticLib") |
⸺ see documentation on linking with #pragma comment vs #link.
Es bastante fácil cometer el error de no combinar compiladores. Como puede ver en la captura de pantalla de la derecha, no puede saber fácilmente qué compilador de Win32 se está utilizando. Esto es algo que podríamos mejorar, pero en este momento enumera la plataforma de destino, no el compilador.
Nuestro compilador ahora emite en cada objeto un registro (un pequeño fragmento de datos) que indica con qué compilador fue construido (por ejemplo, Clang Win32). Al vincular, el vinculador recibe un conjunto de archivos de objetos y bibliotecas, en orden en el comando línea. Observa el primer objeto con el que se vincula y señala que espera que todos los demás objetos se compilen con el mismo compilador que el primero. Para cada objeto en el que se vincula (y dada una biblioteca, que es solo un conjunto de objetos, para cada objeto en la biblioteca), verifica si fue construido con el compilador que espera.
En caso contrario, emite la advertencia anterior, que también puedes ver en la imagen de la derecha. Puede ver que enumera el objeto erróneo y con qué se construyó, y también explica por qué estaba buscando un compilador diferente. Esto está destinado a ayudarlo a diagnosticar su configuración de compilación.
TLDR
Resumen rápido: mezclar archivos de objetos creados con dos compiladores en un binario es una mala idea. El enlazador le dará una advertencia si lo hace y le dirá qué está construido con qué para que pueda solucionarlo. ¡Esto soluciona problemas del vinculador y soluciona problemas de estabilidad de la aplicación!
Otras lecturas
Componentes de empaquetado o bibliotecas escritas en compiladores de Win32 Classic y Clang C ++
Esta nueva página de docwiki analiza la advertencia del vinculador, pero también tiene un poco más de información. Aborda cómo usar clang o binarios clásicos si eres un desarrollador de aplicaciones y estás creando aplicaciones con varias partes (tal vez enlazando con una biblioteca de C ++ de código abierto que también estás construyendo), y también tiene otra sección para si eres una biblioteca desarrollador (por ejemplo, escribir componentes o bibliotecas y distribuirlos a sus clientes).
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition