Incompatibilidade detectada para 'RuntimeLibrary'

114

Baixei e extraí o Crypto ++ em C: \ cryptopp. Usei o Visual Studio Express 2012 para construir todos os projetos internos (conforme instruído no readme), e tudo foi construído com sucesso. Então fiz um projeto de teste em alguma outra pasta e adicionei cryptolib como uma dependência. Depois disso, adicionei o caminho de inclusão para poder incluir facilmente todos os cabeçalhos. Quando tentei compilar, recebi um erro sobre símbolos não resolvidos.

Para remediar isso, adicionei o C:\cryptopp\Win32\Output\Debug\cryptlib.liblink de dependências adicionais. Agora recebo este erro:

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

Eu também recebo:

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

O código que tentei compilar era simples (peguei em outro site):

#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;
}

Alguma ideia de como consertar isso? Na verdade, só preciso do SHA-256 agora, nada mais. Estou usando o Windows 7 de 64 bits e baixei o VS C ++ hoje, então deve ser a versão mais recente.

Momonga
fonte
1
Eu defini a biblioteca de tempo de execução do meu projeto para depuração Multi-threaded (essa era a configuração usada em crypto ++) e agora ela compila! :) Muito obrigado.
Momonga
Os problemas ocorreram muito antes, durante a execução VCUpgrade. Você está vendo sintomas de falha de VCUpgrade que foi relatado como um sucesso para você.
jww

Respostas:

233

(Isso já foi respondido nos comentários, mas como não há uma resposta real , estou escrevendo isso.)

Esse problema surge em versões mais recentes do Visual C ++ (as versões mais antigas geralmente vinculavam silenciosamente o programa e ele travava e queimava no tempo de execução). Isso significa que algumas das bibliotecas que você está vinculando ao seu programa (ou mesmo algumas das fontes arquivos dentro do seu próprio programa) estão usando versões diferentes do CRT (a biblioteca C RunTime).

Para corrigir esse erro, você precisa ir para o seu Project Properties(e / ou aqueles das bibliotecas que você está usando), então para C/C++, então Code Generation, e verifique o valor de Runtime Library; deve ser exatamente o mesmo para todos os arquivos e bibliotecas que você está vinculando. (As regras são um pouco mais relaxadas para vincular a DLLs, mas não vou entrar no "porquê" e em mais detalhes aqui.)

Existem atualmente quatro opções para esta configuração:

  1. Depuração multithread
  2. DLL de depuração multithreaded
  3. Lançamento Multithread
  4. DLL de liberação multithread

Seu problema particular parece resultar de você vincular uma biblioteca construída com "Multithreaded Debug" (isto é, CRT de depuração estática multithread) contra um programa que está sendo construído usando a configuração " DLL de depuração multithreaded " (ou seja, CRT de depuração multithread dinâmica). esta configuração na biblioteca ou no seu programa. Por enquanto, sugiro mudar isso em seu programa.

Observe que, como os projetos do Visual Studio usam diferentes conjuntos de configurações de projeto para depurar e liberar compilações (e compilações de 32/64 bits), você deve certificar-se de que as configurações correspondem a todas essas configurações de projeto.

Para (algumas) mais informações, você pode ver estes (link de um comentário acima):

  1. Aviso de ferramentas de linker LNK4098 no MSDN
  2. / MD, / ML, / MT, / LD (usar biblioteca de tempo de execução) no MSDN
  3. Erros de compilação com VC11 Beta - mistura de libs MTd com exes MDd falha ao vincular no Bugzilla @ Mozilla

ATUALIZAÇÃO : (Isso é em resposta a um comentário que pergunta por que tanto cuidado deve ser tomado.)

Se duas partes do código que estamos vinculando estão vinculadas e usando a biblioteca padrão, a biblioteca padrão deve ser a mesma para ambas, a menos que muito cuidado seja tomado sobre como nossas duas partes do código interagem e transmitem os dados. Geralmente, eu diria que para quase todas as situações apenas use exatamente a mesma versão do tempo de execução da biblioteca padrão (em relação à depuração / lançamento, threads e, obviamente, a versão do Visual C ++, entre outras coisas como depuração do iterador, etc.)

A parte mais importante do problema é esta: ter a mesma ideia sobre o tamanho dos objetos de cada lado de uma chamada de função .

Considere, por exemplo, que as duas partes de código acima são chamadas Ae B. A é compilado em uma versão da biblioteca padrão e B em outra. Na visão de A, algum objeto aleatório que uma função padrão retorna a ele (por exemplo, um bloco de memória ou um iterador ou um FILEobjeto ou qualquer outro) tem algum tamanho e layout específicos (lembre-se de que o layout da estrutura é determinado e fixado em tempo de compilação em C / C ++.) Por qualquer uma das várias razões, a ideia de B do tamanho / layout dos mesmos objetos é diferente (pode ser devido a informações adicionais de depuração, evolução natural das estruturas de dados ao longo do tempo, etc.)

Agora, se A chama a biblioteca padrão e obtém um objeto de volta, então passa esse objeto para B, e B toca aquele objeto de qualquer forma, as chances são de que B bagunce o objeto (por exemplo, escreva o campo errado, ou passe o fim disso, etc.)

O acima não é o único tipo de problema que pode acontecer. Objetos internos globais ou estáticos na biblioteca padrão também podem causar problemas. E também existem classes de problemas mais obscuros.

Tudo isso fica mais estranho em alguns aspectos ao usar DLLs (biblioteca de tempo de execução dinâmico) em vez de libs (biblioteca de tempo de execução estática).

Essa situação pode se aplicar a qualquer biblioteca usada por duas partes do código que funcionam juntas, mas a biblioteca padrão é usada pela maioria (se não por quase todos) dos programas, e isso aumenta as chances de conflito.

O que descrevi é obviamente uma versão diluída e simplificada da bagunça real que espera por você se você misturar versões de biblioteca. Espero que isso lhe dê uma ideia de por que você não deve fazer isso!

yzt
fonte
Eu estou um pouco confuso. O erro de OP é LNK2038 . Como isso não acontece com todas as libs, suspeito que o Crypto ++ mexe com algumas configurações de CRT que tornam impossível misturar tipos de CRT - geralmente é apenas um aviso (LNK4098) e você pode estar seguro se souber o que faz (não recomendado, mas possível com limitações, consulte, por exemplo, stackoverflow.com/a/19944935/948581 ). Não sei por que o Crypto ++ é afetado dessa forma.
1
@Tibo: não são bibliotecas de importação para DLLs; Eu acredito que o Crypto ++ está, na verdade, sendo vinculado estaticamente ao programa aqui. Isso significa que qualquer incompatibilidade na biblioteca padrão sendo vinculada em um módulo em relação a outro (provavelmente) viola a "Regra de Uma Definição". O que é ruim. Isso não costumava ser um erro, já que o vinculador nem mesmo era capaz de detectar isso (os nomes de função / tipo eram os mesmos, mas seus corpos e definições diferiam significativamente) até o VC10, quando o vinculador / bibliotecário começou a "marcar" os módulos produziu com informações extras sobre a configuração da compilação ...
yzt
@Tibo: ... (continuação do comentário anterior) Por exemplo, observe o primeiro bloco de erros que o OP está relatando. Lá, " RuntimeLibrary " é uma tag na biblioteca Crypto ++ e no arquivo objeto para o programa do OP, e seu valor é " MDd_DynamicDebug " para um deles e " MTd_StaticDebug " para o outro. Dessa forma, o vinculador que está tentando vincular dois arquivos-objeto pode detectar e relatar uma classe totalmente nova de erros, visto que os vinculadores que produziram esses arquivos-objeto os marcaram com qualquer informação relevante, especialmente quaisquer configurações que potencialmente violariam o ODR.
yzt,
Embora eu concorde totalmente com você, ainda há uma área de mistério aqui. Quanto ao problema do OP, acho que ele está incluindo "dll.h" do Crypto ++ e, em seguida, tenta vincular à biblioteca estática em vez da biblioteca de importação da DLL. Mas eu vi exatamente os mesmos erros em um computador, não em outro (VS2013 ultimate sp4 -> erro, VS2013 community sp5 -> ok) ...
1
@yzt Eu descobri uma solução. Em vez de usar / ZW swicth, o Windows fornece uma maneira de usar a API WinRT via COM usando um wrapper chamado WRL. Acontece que não usar / ZW torna a codificação um pouco difícil, pois oculta detalhes de implementação COM, mas é possível usar WinRT sem / ZW.
Sahil Singh
3

Baixei e extraí o Crypto ++ em C: \ cryptopp. Usei o Visual Studio Express 2012 para construir todos os projetos internos (conforme instruído no readme), e tudo foi construído com sucesso. Então fiz um projeto de teste em alguma outra pasta e adicionei cryptolib como uma dependência.

A conversão provavelmente não foi bem-sucedida. A única coisa que deu certo foi a execução do VCUpgrade. A conversão real falhou, mas você não sabe até experimentar os erros que está vendo. Para obter alguns detalhes, consulte Visual Studio no wiki Crypto ++.


Alguma ideia de como consertar isso?

Para resolver seus problemas, você deve fazer o download vs2010.zipse quiser vinculação estática do tempo de execução C / C ++ ( /MTou /MTd) ou vs2010-dynamic.zipse quiser vinculação dinâmica do tempo de execução C / C ++ ( /MTou /MTd). Ambos corrigem as falhas latentes e silenciosas produzidas pelo VCUpgrade.


vs2010.zip, vs2010-dynamic.zipe vs2005-dynamic.zipsão construídos a partir das fontes GitHub mais recentes . No momento em que este livro foi escrito (1 de junho de 2016), isso era efetivamente pré-Crypto ++ 5.6.4. Se estiver usando arquivos ZIP com um Crypto ++ de nível inferior, como 5.6.2 ou 5.6.3, você terá pequenos problemas.

Estou ciente de que existem dois pequenos problemas. Primeiro é renomear bench.cppparabench1.cpp . Seu erro é:

  • 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)

A correção é (1) abrir cryptest.vcxprojno bloco de notas, localizar bench1.cppe renomeá-lo para bench.cpp. Ou (2) renomeie bench.cpppara bench1.cppno sistema de arquivos. Não exclua este arquivo.

O segundo problema é um pouco mais complicado porque é um alvo móvel. Versões de nível inferior, como 5.6.2 ou 5.6.3, não possuem as classes mais recentes disponíveis no GitHub . Os arquivos de classe ausentes incluem 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.

A correção é remover os arquivos de origem ausentes dos arquivos de projeto do Visual Studio, pois eles não existem para as versões de nível inferior.

Outra opção é adicionar os arquivos de classe ausentes das fontes mais recentes, mas pode haver complicações. Por exemplo, muitas das fontes dependem sutilmente das últimas config.h, cpu.he cpu.cpp. A "sutileza" é que você não vai perceber que está tendo uma aula de baixo desempenho.

Um exemplo de classe de baixo desempenho é BLAKE2. config.hadiciona detecção de ARM-32 e ARM-64 em tempo de compilação. cpu.he cpu.cppadiciona detecção de instrução ARM em tempo de execução, que depende da detecção em tempo de compilação. Se você adicionar BLAKE2 sem os outros arquivos, nenhuma detecção ocorrerá e você obterá uma implementação C / C ++ direta. Você provavelmente não vai perceber que está perdendo a oportunidade NEON, que funciona em torno de 9 a 12 ciclos por byte versus 40 ciclos por byte ou mais para o C / C ++ básico.

jww
fonte
Segui as instruções no wiki cryptopp, baixei o vs2010-dynamic.zip e colei seu conteúdo no código cryptopp563. Construído e com alguns arquivos de origem faltando. Não há problema, o wiki diz que o zip é para o projeto mais recente no github, e apenas exclua todos os arquivos ausentes. Excluído. Agora, o projeto simplesmente não cria: 4 erros de link, um exemplo: erro LNK2001: símbolo externo não resolvido "void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)" (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Yaniv
Acontece que havia um bench.cpp que estava faltando no projeto. Mas mesmo depois disso, ele não compilou até que eu apliquei essa correção a fiptest.cpp github.com/weidai11/cryptopp/pull/151/files?diff=split Eu gostaria que eles fizessem alguma ordem nisso, como adicionar os arquivos zip do projeto em git ou algo assim. E sim, esqueci de dizer que meu compilador é a atualização 2 do VS2015. Resumindo, siga as dicas que escrevi e funciona.
Yaniv
@Yaniv - Para o primeiro comentário, o que você recomenda para que outros usuários não tenham problemas? Para o segundo comentário, planejamos pegar o patch assim que o tivermos testado totalmente. Há algo que possamos fazer nesse meio tempo? (Eu adicionei informações adicionais a esta resposta, mas quero garantir que os usuários não tenham problemas).
jww 01 de
Em primeiro lugar, muito obrigado por fazer isso. Crypto ++ realmente arrasa. Em relação aos problemas de compilação, tente manter os arquivos do Windows Sln e do projeto compatíveis com os arquivos mais recentes do projeto e, como esses arquivos mudam, é claro que essas compilações do Windows devem estar de alguma forma vinculadas ao código-base e talvez até mesmo na árvore de origem. Se isso for demais, pelo menos certifique-se de que o arquivo zip com o ambiente de compilação do Visual Studio seja compatível com a versão oficial estável atual.
Yaniv
Em relação ao patch para fiptest.cpp - parece ser algo diferente sobre o VS2015, então acho que qualquer pessoa que deseje usar o VS2015 precisa aplicar este patch. É apenas mais um caso em um bloco #ifdef que parece definir o retorno de chamada de depuração correto para VS2015 e é realmente fácil de corrigir manualmente.
Yaniv
3

Eu tive esse problema junto com incompatibilidade em ITERATOR_DEBUG_LEVEL. Afinal, como um problema de domingo à noite parecia bom e bom para ir, fiquei desconcertado por algum tempo. Trabalhando no IDE VS2017 (Solution Explorer), recentemente adicionei / copiei uma referência de arquivo de origem para o meu projeto (ctrl-drag) de outro projeto. Olhando em propriedades-> C / C ++ / Pré-processador - no nível do arquivo de origem, não no nível do projeto - notei que em uma configuração de versão _DEBUG foi especificado em vez de NDEBUG para este arquivo de origem. Que foi toda a mudança necessária para se livrar do problema.

Jan
fonte
1

O problema pode ser resolvido adicionando CRT de msvcrtd.lib na biblioteca do vinculador. Porque cryptlib.lib usou a versão CRT de depuração.

abhijithkp
fonte