Error de coincidencia detectado para 'RuntimeLibrary'

114

Descargué y extraje Crypto ++ en C: \ cryptopp. Usé Visual Studio Express 2012 para construir todos los proyectos internos (como se indica en el archivo Léame), y todo se construyó correctamente. Luego hice un proyecto de prueba en otra carpeta y agregué cryptolib como dependencia. Después de eso, agregué la ruta de inclusión para poder incluir fácilmente todos los encabezados. Cuando intenté compilar, recibí un error sobre los símbolos sin resolver.

Para remediar eso, agregué C:\cryptopp\Win32\Output\Debug\cryptlib.libpara vincular dependencias adicionales. Ahora me sale este error:

Error   1   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(cryptlib.obj)    CryptoTest
Error   2   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(iterhash.obj)    CryptoTest
Error   3   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(sha.obj) CryptoTest
Error   4   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(pch.obj) CryptoTest
Error   5   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(misc.obj)    CryptoTest
Error   6   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(queue.obj)   CryptoTest
Error   7   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(algparam.obj)    CryptoTest
Error   8   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(filters.obj) CryptoTest
Error   9   error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(fips140.obj) CryptoTest
Error   10  error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(cpu.obj) CryptoTest
Error   11  error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in program.obj    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\cryptlib.lib(mqueue.obj)  CryptoTest

También obtengo:

Error   12  error LNK2005: "public: __thiscall std::_Container_base12::_Container_base12(void)" (??0_Container_base12@std@@QAE@XZ) already defined in cryptlib.lib(cryptlib.obj)    C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Error   13  error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12@std@@QAE@XZ) already defined in cryptlib.lib(cryptlib.obj)   C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Error   14  error LNK2005: "public: void __thiscall std::_Container_base12::_Orphan_all(void)" (?_Orphan_all@_Container_base12@std@@QAEXXZ) already defined in cryptlib.lib(cryptlib.obj)   C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Error   15  error LNK2005: "public: __thiscall std::locale::id::id(unsigned int)" (??0id@locale@std@@QAE@I@Z) already defined in cryptlib.lib(iterhash.obj) C:\Data\Work\C++ VS\CryptoTest\CryptoTest\msvcprtd.lib(MSVCP110D.dll)   CryptoTest
Warning 16  warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use /NODEFAULTLIB:library   C:\Data\Work\C++ VS\CryptoTest\CryptoTest\LINK  CryptoTest
Error   17  error LNK1169: one or more multiply defined symbols found   C:\Data\Work\C++ VS\CryptoTest\Debug\CryptoTest.exe 1   1   CryptoTest

El código que intenté compilar fue simple (lo obtuve de otro sitio):

#include <iostream>
#include <string>
#include "sha.h"
#include "hex.h"
using namespace std;

string SHA256(string data) {
    byte const* pbData = (byte*) data.data();
    unsigned int nDataLen = data.size();
    byte abDigest[32];

    CryptoPP::SHA256().CalculateDigest(abDigest, pbData, nDataLen);

    return string((char*)abDigest);
}

int main(void) {

    return 0;
}

Alguna idea de cómo solucionar este problema? Realmente solo necesito SHA-256 en este momento, nada más. Estoy usando Windows 7 de 64 bits y descargué VS C ++ hoy, por lo que debería ser la versión más nueva.

Momonga
fuente
1
Configuré la biblioteca de tiempo de ejecución de mi proyecto en depuración de subprocesos múltiples (esa era la configuración utilizada en crypto ++) y ahora se compila. :) Muchas gracias.
Momonga
Los problemas ocurrieron mucho antes cuando corrió VCUpgrade. Está viendo síntomas de la falla de VCUpgrade que se le informó como un éxito .
jww

Respuestas:

233

(Esto ya está respondido en los comentarios, pero como carece de una respuesta real , estoy escribiendo esto).

Este problema surge en las versiones más recientes de Visual C ++ (las versiones anteriores generalmente solo vinculaban silenciosamente el programa y se bloqueaba y quemaba en tiempo de ejecución). Significa que algunas de las bibliotecas que está vinculando con su programa (o incluso algunas de las fuentes archivos dentro de su programa) están usando diferentes versiones de CRT (la biblioteca C RunTime).

Para corregir este error, debe ir a su Project Properties(y / o las de las bibliotecas que está utilizando), luego a C/C++, luego Code Generation, y verificar el valor de Runtime Library; esto debería ser exactamente igual para todos los archivos y bibliotecas que está vinculando. (Las reglas son un poco más relajadas para la vinculación con archivos DLL, pero no voy a entrar en el "por qué" ni en más detalles aquí).

Actualmente hay cuatro opciones para esta configuración:

  1. Depuración multiproceso
  2. DLL de depuración multiproceso
  3. Lanzamiento multiproceso
  4. DLL de versión multiproceso

Su problema particular parece provenir de que usted vincule una biblioteca construida con "Depuración multiproceso" (es decir, CRT de depuración multiproceso estático) con un programa que se está construyendo usando la " DLL de depuración multiproceso configuración " " (es decir, CRT de depuración multiproceso dinámico). esta configuración en la biblioteca o en su programa. Por ahora, sugiero cambiar esto en su programa.

Tenga en cuenta que, dado que los proyectos de Visual Studio usan diferentes conjuntos de configuraciones de proyecto para depurar y publicar compilaciones (y compilaciones de 32/64 bits), debe asegurarse de que la configuración coincida en todas estas configuraciones de proyecto.

Para (algo) más información, puede ver estos (enlazados desde un comentario anterior):

  1. Advertencia de las herramientas del vinculador LNK4098 en MSDN
  2. / MD, / ML, / MT, / LD (Usar biblioteca en tiempo de ejecución) en MSDN
  3. Errores de compilación con VC11 Beta: la combinación de bibliotecas de MTd con ex de MDd no se puede vincular en Bugzilla @ Mozilla

ACTUALIZACIÓN : (Esto es en respuesta a un comentario que pregunta la razón por la que se debe tener tanto cuidado).

Si dos fragmentos de código que estamos vinculando juntos se vinculan y utilizan la biblioteca estándar, entonces la biblioteca estándar debe ser la misma para ambos, a menos que sea excelente. cuidado con la forma en que nuestros dos fragmentos de código interactúan y pasan los datos. En general, diría que para casi todas las situaciones simplemente use exactamente la misma versión del tiempo de ejecución de la biblioteca estándar (con respecto a la depuración / liberación, subprocesos y, obviamente, la versión de Visual C ++, entre otras cosas como la depuración del iterador, etc.)

La parte más importante del problema es la siguiente: tener la misma idea sobre el tamaño de los objetos a cada lado de una llamada de función .

Considere, por ejemplo, que los dos fragmentos de código anteriores se denominan Ay B. A se compila con una versión de la biblioteca estándar y B con otra. En la vista de A, algún objeto aleatorio al que una función estándar le devuelve (por ejemplo, un bloque de memoria o un iterador o un FILEobjeto o lo que sea) tiene un tamaño y diseño específicos (recuerde que el diseño de la estructura se determina y se fija en el momento de la compilación en C / C ++.) Por varias razones, la idea de B sobre el tamaño / diseño de los mismos objetos es diferente (puede deberse a información adicional de depuración, evolución natural de las estructuras de datos a lo largo del tiempo, etc.)

Ahora, si A llama a la biblioteca estándar y recupera un objeto, luego pasa ese objeto a B, y B toca ese objeto de alguna manera, es probable que B estropee ese objeto (por ejemplo, escriba el campo incorrecto o más allá del final de eso, etc.)

Lo anterior no es el único tipo de problemas que pueden ocurrir. Los objetos internos globales o estáticos de la biblioteca estándar también pueden causar problemas. Y también hay clases de problemas más oscuras.

Todo esto se vuelve más extraño en algunos aspectos cuando se usan DLL (biblioteca dinámica en tiempo de ejecución) en lugar de libs (biblioteca estática en tiempo de ejecución).

Esta situación puede aplicarse a cualquier biblioteca utilizada por dos piezas de código que funcionan juntas, pero la biblioteca estándar es utilizada por la mayoría (si no casi todos) los programas, y eso aumenta las posibilidades de conflicto.

Lo que he descrito es, obviamente, una versión diluida y simplificada del lío real que le espera si mezcla las versiones de la biblioteca. ¡Espero que te dé una idea de por qué no deberías hacerlo!

yzt
fuente
Estoy un poco confundido. El error de OP es LNK2038 . Como no sucede con todas las bibliotecas, sospecho que Crypto ++ juega con algunas configuraciones de CRT que hacen que sea imposible mezclar sabores de CRT; por lo general, es solo una advertencia (LNK4098) y puede estar seguro si sabe lo que hace (no recomendado, pero posible con limitaciones, consulte, por ejemplo, stackoverflow.com/a/19944935/948581 ). Sin embargo, no sé por qué Crypto ++ se ve afectado de esta manera.
1
@Tibo: estas no son bibliotecas de importación para DLL; Creo que Crypto ++ en realidad está vinculado estáticamente con el programa aquí. Esto significa que cualquier discrepancia en la biblioteca estándar que se vincula en un módulo con otro (probablemente) viola la "Regla de una definición". Cual es malo. Esto no solía ser un error, ya que el vinculador ni siquiera pudo detectar esto (los nombres de función / tipo eran los mismos, pero sus cuerpos y definiciones diferían significativamente) hasta VC10 cuando el vinculador / bibliotecario comenzó a "etiquetar" los módulos produjo con información adicional sobre la configuración de la compilación ...
yzt
@Tibo: ... (continúa del comentario anterior) Por ejemplo, mire el primer bloque de errores que informa el OP. Allí, " RuntimeLibrary " es una etiqueta tanto en la biblioteca Crypto ++ como en el archivo de objeto para el programa del OP, y su valor es " MDd_DynamicDebug " para uno de ellos y " MTd_StaticDebug " para el otro. De esta manera, el vinculador que está tratando de vincular dos archivos de objeto juntos puede detectar e informar una clase completamente nueva de errores, dado que los vinculadores que produjeron esos archivos de objeto los etiquetaron con cualquier información relevante, particularmente cualquier configuración que potencialmente violaría ODR.
yzt
Si bien estoy bastante de acuerdo con usted, todavía hay un área de misterio aquí. En cuanto al problema del OP, supongo que está incluyendo "dll.h" de Crypto ++, y luego intenta enlazar con la biblioteca estática en lugar de la biblioteca de importación de la DLL. Pero he visto exactamente los mismos errores en una computadora, no en otra (VS2013 ultimate sp4 -> error, VS2013 community sp5 -> ok) ...
1
@yzt Descubrí una solución. En lugar de usar / ZW swicth, Windows proporciona una forma de usar la API de WinRT a través de COM usando un contenedor llamado WRL. Es solo que no usar / ZW hace que la codificación sea un poco difícil ya que oculta los detalles de implementación COM, pero es posible usar WinRT sin / ZW.
Sahil Singh
3

Descargué y extraje Crypto ++ en C: \ cryptopp. Usé Visual Studio Express 2012 para construir todos los proyectos internos (como se indica en el archivo Léame), y todo se construyó correctamente. Luego hice un proyecto de prueba en otra carpeta y agregué cryptolib como dependencia.

Probablemente la conversión no se haya realizado correctamente. Lo único que tuvo éxito fue la ejecución de VCUpgrade. La conversión real falló, pero no lo sabrá hasta que experimente los errores que está viendo. Para obtener algunos detalles, consulte Visual Studio en la wiki de Crypto ++.


Alguna idea de cómo solucionar este problema?

Para resolver sus problemas, debe descargar vs2010.zipsi desea un enlace de tiempo de ejecución de C / C ++ estático ( /MTo /MTd), o vs2010-dynamic.zipsi desea un enlace de tiempo de ejecución de C / C ++ dinámico ( /MTo /MTd). Ambos arreglan los fallos silenciosos y latentes producidos por VCUpgrade.


vs2010.zip, vs2010-dynamic.zipY vs2005-dynamic.zipse construyen a partir de las últimas fuentes de GitHub . En el momento de escribir este artículo (1 de junio de 2016), eso es efectivamente anterior a Crypto ++ 5.6.4. Si está utilizando archivos ZIP con un nivel inferior de Crypto ++, como 5.6.2 o 5.6.3, se encontrará con problemas menores.

Hay dos problemas menores que conozco. Primero es un cambio de nombre de bench.cppabench1.cpp . Su error es:

  • C1083: Cannot open source file: 'bench1.cpp': No such file or directory
  • LNK2001: unresolved external symbol "void __cdecl OutputResultOperations(char const *,char const *,bool,unsigned long,double)" (?OutputResultOperations@@YAXPBD0_NKN@Z)

La solución es (1) abrir cryptest.vcxprojen el bloc de notas, buscar bench1.cppy luego cambiarle el nombre a bench.cpp. O (2) cambiar el nombre bench.cppa bench1.cppen el sistema de archivos. No elimine este archivo.

El segundo problema es un poco más complicado porque es un objetivo en movimiento. A las versiones de nivel inferior, como 5.6.2 o 5.6.3, les faltan las últimas clases disponibles en GitHub . Los archivos de clase que faltan incluyen HKDF (5.6.3), RDRAND (5.6.3), RDSEED (5.6.3), ChaCha (5.6.4), BLAKE2 (5.6.4), Poly1305 (5.6.4), etc.

La solución es eliminar los archivos fuente que faltan de los archivos del proyecto de Visual Studio, ya que no existen para las versiones de nivel inferior.

Otra opción es agregar los archivos de clases que faltan de las fuentes más recientes, pero podría haber complicaciones. Por ejemplo, muchas de las fuentes sutilmente dependen de la última config.h, cpu.hy cpu.cpp. La "sutileza" es que no se dará cuenta de que está obteniendo una clase de bajo rendimiento.

Un ejemplo de clase de bajo rendimiento es BLAKE2. config.hagrega tiempo de compilación de detección ARM-32 y ARM-64. cpu.hy cpu.cppagrega detección de instrucciones ARM en tiempo de ejecución, que depende de la detección del tiempo de compilación. Si agrega BLAKE2 sin los otros archivos, entonces no se produce ninguna detección y obtiene una implementación directa de C / C ++. Probablemente no se dé cuenta de que está perdiendo la oportunidad NEON, que se ejecuta alrededor de 9 a 12 ciclos por byte frente a 40 ciclos por byte más o menos para Vanilla C / C ++.

jww
fuente
Seguí las instrucciones en la wiki de cryptopp, descargué vs2010-dynamic.zip y pegué su contenido en el código cryptopp563. Construido y faltan algunos archivos fuente. No hay problema, la wiki dice que el zip es para el último proyecto en github, y simplemente elimine los archivos faltantes. Eliminado Ahora el proyecto simplemente no se construye: 4 errores de enlace, un ejemplo: error LNK2001: símbolo externo no resuelto "void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)" (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Yaniv
Resultó que faltaba un bench.cpp en el proyecto. Pero incluso después de eso, no se compiló hasta que apliqué esta solución a fiptest.cpp github.com/weidai11/cryptopp/pull/151/files?diff=split Desearía que hicieran algún orden en esto, como agregar los archivos zip del proyecto en git o algo así. Y sí, me olvidé de decir que mi compilador es la actualización 2 de VS2015. En resumen, siga las sugerencias que escribí y funciona.
Yaniv
@Yaniv - Para el primer comentario, ¿qué recomiendas para que otros usuarios no experimenten problemas? Para el segundo comentario, planeamos tomar el parche una vez que lo tengamos completamente probado. ¿Hay algo que podamos hacer mientras tanto? (Agregué información adicional a esta respuesta, pero quiero asegurarme de que los usuarios no tengan problemas).
jww
En primer lugar, muchas gracias por hacer esto. Crypto ++ realmente es genial. Con respecto a los problemas de compilación, intente mantener el sln de Windows y los archivos del proyecto compatibles con los archivos más recientes del proyecto, y dado que estos cambian, por supuesto, estas compilaciones de Windows deberían estar vinculadas de alguna manera al código base, y tal vez incluso estar en el árbol de fuentes. Si eso es demasiado, al menos asegúrese de que el archivo zip con el entorno de compilación de Visual Studio sea compatible con la versión oficial estable actual.
Yaniv
Con respecto al parche para fiptest.cpp, parece ser algo diferente en VS2015, así que supongo que cualquiera que desee usar VS2015 debe aplicar este parche. Es solo otro caso en un bloque #ifdef que parece definir la devolución de llamada de depuración correcta para VS2015, y es realmente fácil de parchear manualmente.
Yaniv
3

Tuve este problema junto con una falta de coincidencia en ITERATOR_DEBUG_LEVEL. Como un problema de los domingos por la noche, después de todo parecía estar bien y bueno, me sentí molesto por un tiempo. Trabajando en el IDE de VS2017 (Explorador de soluciones), recientemente había agregado / copiado una referencia de archivo de origen a mi proyecto (ctrl-drag) de otro proyecto. Mirando las propiedades-> C / C ++ / Preprocesador - en el nivel del archivo fuente, no en el nivel del proyecto - noté que en una configuración de lanzamiento se especificó _DEBUG en lugar de NDEBUG para este archivo fuente. Que fue todo el cambio necesario para solucionar el problema.

ene
fuente
1

El problema se puede resolver agregando CRT de msvcrtd.lib en la biblioteca del vinculador. Porque cryptlib.lib usó la versión CRT de debug.

abhijithkp
fuente