Resolviendo LNK4098: defaultlib 'MSVCRT' entra en conflicto con

216

Esta advertencia:

LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts
  with use of other libs; use /NODEFAULTLIB:library

Es una advertencia bastante común en Visual Studio. Me gustaría entender la razón exacta y la forma correcta (si es que lo hace) de manejarlo.

Esto aparece en una compilación de depuración, compilada con /MDd. El proyecto está vinculado a cosas como ventanas Version.dlly con las pdh.dllque se vinculan MSVCRT.dll. Obviamente, no tengo las versiones de depuración de estos y no puedo compilarlos.

Así que agregué /NODEFAULTLIB:MSVCRTa la línea de comando del vinculador y en realidad eliminó la advertencia. Pero, ¿qué hace esto realmente? ¿Y por qué es necesario?

shoosh
fuente

Respuestas:

273

Hay 4 versiones de las bibliotecas de enlaces CRT presentes en vc \ lib:

  • libcmt.lib: biblioteca estática de enlaces CRT para una compilación de lanzamiento (/ MT)
  • libcmtd.lib: biblioteca de enlaces CRT estática para una compilación de depuración (/ MTd)
  • msvcrt.lib: biblioteca de importación para la versión de lanzamiento DLL del CRT (/ MD)
  • msvcrtd.lib: biblioteca de importación para la versión DLL de depuración del CRT (/ MDd)

Mire las opciones del vinculador, Proyecto + Propiedades, Vinculador, Línea de comando. Observe cómo estas bibliotecas no se mencionan aquí. El vinculador descubre automáticamente qué modificador / M utilizó el compilador y qué .lib debería vincularse a través de una directiva de comentario #pragma. Un poco importante, obtendría errores de enlace horribles y errores de tiempo de ejecución difíciles de diagnosticar si hubiera una discrepancia entre la opción / M y el .lib con el que se vincula.

Verá el mensaje de error que citó cuando se le indica al vinculador que se vincule a msvcrt.lib y libcmt.lib. Lo que sucederá si vincula el código que se compiló con / MT con el código que se vinculó con / MD. Solo puede haber una versión de la CRT.

/ NODEFAULTLIB le dice al enlazador que ignore la directiva de comentario #pragma que se generó a partir del código compilado / MT. Esto podría funcionar, aunque una serie de otros errores de enlazador no es infrecuente. Cosas como errno , que es un int externo en la versión estática de CRT pero macro-ed a una función en la versión DLL. A muchos otros les gusta eso.

Bueno, solucione este problema de la manera correcta, busque el archivo .obj o .lib que está vinculando que se compiló con la opción incorrecta / M. Si no tiene ni idea, puede encontrarlo agrupando los archivos .obj / .lib para "/ MT"

Por cierto: los ejecutables de Windows (como version.dll) tienen su propia versión CRT para hacer su trabajo. Se encuentra en c: \ windows \ system32, no puede usarlo de manera confiable para sus propios programas, sus encabezados CRT no están disponibles en ninguna parte. La DLL CRT utilizada por su programa tiene un nombre diferente (como msvcrt90.dll).

Hans Passant
fuente
2
Gracias a esta publicación, seguí buscando un .lib que todavía usaba / MDd y finalmente encontré uno. Gracias, +1
ceztko
64
Un truco que acabo de aprender para rastrear las bibliotecas que están utilizando las bibliotecas CRT incorrectas es agregar /verbose:liba las opciones de vinculador adicionales. Muestra el orden en que se cargan los archivos .lib, lo que le permite ver dónde se
introdujo el archivo
1
Hans, ¿qué tan peligroso es? Si no podemos solucionarlo (obtenemos una biblioteca compilada de nuestro proveedor), ¿qué consecuencias podemos enfrentar?
Ivan Nikitin
3
He encontrado @obmarg' comentario útil, pero todavía no estaba seguro de cómo utilizar la salida verbosa hasta que encontré msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx que dice la voluntad salida detallada solo le diré todas las bibliotecas de tiempo de ejecución involucradas en el problema del enlace. Aún debe averiguar qué entrada de enlace se ha compilado con la Biblioteca de tiempo de ejecución en conflicto.
buzz3791
44
@ buzz3791 use / verbose en lugar de / verbose: lib. La información mostrada incluye el proceso de búsqueda de la biblioteca y enumera cada biblioteca y nombre de objeto (con la ruta completa), el símbolo que se resuelve de la biblioteca y una lista de objetos que hacen referencia al símbolo. / verbose puede mostrar toda la información que necesitas para encontrar al malo que causa los conflictos.
Yang Kui
46

Significa que uno de los dlls dependientes se compila con una biblioteca de tiempo de ejecución diferente .

Proyecto -> Propiedades -> C / C ++ -> Generación de código -> Biblioteca de tiempo de ejecución

Revise todas las bibliotecas y vea que están compiladas de la misma manera.

Más sobre este error en este enlace:

advertencia LNK4098: defaultlib "LIBCD" entra en conflicto con el uso de otras bibliotecas

Yochai Timmer
fuente
Esa fue la razón del error! Gracias por el consejo.
rkachach
1
Esta es la mejor respuesta para programadores menos experimentados.
Meolic
32

En mi opinión, este enlace de Yochai Timmer fue muy bueno y relevante, pero doloroso de leer. Escribí un resumen.

Yochai, si alguna vez lees esto, mira la nota al final.


Para la publicación original, lea: advertencia LNK4098: defaultlib "LIBCD" entra en conflicto con el uso de otras bibliotecas

Error

ENLACE: advertencia LNK4098: defaultlib "LIBCD" entra en conflicto con el uso de otras librerías; use / NODEFAULTLIB: biblioteca

Sentido

una parte del sistema se compiló para usar una biblioteca estándar de un solo subproceso (libc) con información de depuración (libcd) que está estáticamente vinculada

mientras que otra parte del sistema se compiló para usar una biblioteca estándar de subprocesos múltiples sin información de depuración que reside en un archivo DLL y utiliza enlaces dinámicos

Cómo resolver

  • Ignora la advertencia, después de todo, solo es una advertencia. Sin embargo, su programa ahora contiene múltiples instancias de las mismas funciones.

  • Utilice la opción de enlace / NODEFAULTLIB: lib. Esta no es una solución completa, incluso si puede hacer que su programa se vincule de esta manera, está ignorando una señal de advertencia: el código se ha compilado para diferentes entornos, parte de su código puede compilarse para un modelo de subproceso único mientras que otro código es multihilo

  • [...] recorra todas sus bibliotecas y asegúrese de que tengan la configuración de enlace correcta

En este último, como se menciona en la publicación original, pueden surgir dos problemas comunes:

  • Tiene una biblioteca de terceros que está vinculada de manera diferente a su aplicación.

  • Tiene otras directivas incrustadas en su código: normalmente este es el MFC. Si algún módulo en su sistema se vincula con MFC, todos sus módulos deben vincularse nominalmente con la misma versión de MFC.

Para esos casos, asegúrese de comprender el problema y decidir entre las soluciones.


Nota: quería incluir ese resumen del enlace de Yochai Timmer en su propia respuesta, pero como algunas personas tienen problemas para revisar las ediciones correctamente, tuve que escribirlo en una respuesta separada. Lo siento

ForceMagic
fuente
7

Recibo esto cada vez que quiero crear una aplicación en VC ++.

Haga clic con el botón derecho en el proyecto, seleccione Propiedades y luego en 'Propiedades de configuración | C / C ++ | Generación de código ', seleccione "Depuración de subprocesos múltiples (/ MTd)" para la configuración de depuración.

Tenga en cuenta que esto no cambia la configuración de su configuración de lanzamiento: deberá ir a la misma ubicación y seleccionar "Multi-thread (/ MT)" para el lanzamiento.

usuario1016736
fuente
4

Haga clic con el botón derecho en el proyecto, seleccione Propiedades y luego en 'Propiedades de configuración | Linker | Entrada | Ignore la biblioteca específica y escriba msvcrtd.lib

raehee
fuente