Resolvendo LNK4098: defaultlib 'MSVCRT' entra em conflito com


216

Este aviso:

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

é um aviso bastante comum no Visual Studio. Eu gostaria de entender o motivo exato e a maneira correta (se houver) de lidar com isso.

Isso aparece em uma compilação de depuração, compilada com /MDd. O projeto está vinculado a coisas como janelas Version.dlle às pdh.dllquais elas se vinculam MSVCRT.dll. Obviamente, eu não tenho as versões de depuração delas e não posso compilá-las.

Então eu adicionei /NODEFAULTLIB:MSVCRTà linha de comando do vinculador e ele realmente removeu o aviso. Mas o que isso realmente faz? E porque é necessário?

Respostas:


273

Existem 4 versões das bibliotecas de links CRT presentes em vc \ lib:

  • libcmt.lib: biblioteca estática de links CRT para uma compilação de versão (/ MT)
  • libcmtd.lib: biblioteca estática de links CRT para uma compilação de depuração (/ MTd)
  • msvcrt.lib: biblioteca de importação para a versão DLL do CRT (/ MD)
  • msvcrtd.lib: biblioteca de importação para a versão DLL de depuração do CRT (/ MDd)

Observe as opções do vinculador, Projeto + Propriedades, Vinculador, Linha de comando. Observe como essas bibliotecas não são mencionadas aqui. O vinculador descobre automaticamente qual opção / M foi usada pelo compilador e qual .lib deve ser vinculado por meio de uma diretiva de comentário #pragma. Meio importante, você obteria erros de link horríveis e difíceis de diagnosticar erros de tempo de execução se houvesse uma incompatibilidade entre a opção / M e o .lib ao qual você vincula.

Você verá a mensagem de erro que você citou quando o vinculador for solicitado a vincular ao msvcrt.lib e libcmt.lib. O que acontecerá se você vincular o código que foi compilado com / MT com o código que foi vinculado com / MD. Pode haver apenas uma versão do CRT.

/ NODEFAULTLIB diz ao vinculador para ignorar a diretiva de comentário #pragma que foi gerada a partir do código compilado / MT. Isso pode funcionar, embora uma série de outros erros do vinculador não seja incomum. Coisas como errno , que é um int externo na versão estática do CRT, mas com macro para uma função na versão DLL. Muitos outros assim.

Bem, corrija esse problema da maneira certa, localize o arquivo .obj ou .lib que você está vinculando que foi compilado com a opção / M errada. Se você não tem idéia, poderá encontrá-lo preenchendo os arquivos .obj / .lib para "/ MT"

Btw: os executáveis ​​do Windows (como version.dll) têm sua própria versão CRT para realizar seu trabalho. Ele está localizado em c: \ windows \ system32, você não pode usá-lo com segurança em seus próprios programas, seus cabeçalhos CRT não estão disponíveis em nenhum lugar. A DLL CRT usada pelo seu programa tem um nome diferente (como msvcrt90.dll).


2
Graças a este post, continuei procurando um .lib que ainda estava usando o / MDd e finalmente encontrei um! Obrigado, +1
ceztko 9/11/11

64
Um truque que aprendi a rastrear bibliotecas que estão puxando as bibliotecas CRT erradas é adicionar /verbose:libàs opções adicionais do vinculador. Ele mostra a fim de que .lib são carregados, o que lhe permite ver onde a incorreta foi puxado.
obmarg

1
Hans, como é perigoso? Se não podemos corrigi-lo (obtemos uma lib compilada de nosso fornecedor), que consequências podemos enfrentar?
Ivan Nikitin

3
Eu achei o comentário do @obmarg útil, mas ainda não tinha certeza de como usar a saída detalhada até encontrar msdn.microsoft.com/en-us/library/aa267384(v=vs.60).aspx, que diz que a saída detalhada será informe apenas todas as bibliotecas de tempo de execução envolvidas no problema do link. Você ainda precisa descobrir qual entrada de link foi compilada com a Runtime Library conflitante.
precisa saber é o seguinte

4
@ buzz3791 use / verbose em vez de / verbose: lib. As informações exibidas incluem o processo de pesquisa da biblioteca e listam cada nome de biblioteca e objeto (com caminho completo), o símbolo sendo resolvido a partir da biblioteca e uma lista de objetos que fazem referência ao símbolo. / verbose pode exibir todas as informações necessárias para encontrar o bandido que causa os conflitos.
Yang Kui

46

Isso significa que uma das DLLs dependentes é compilada com uma biblioteca de tempo de execução diferente .

Projeto -> Propriedades -> C / C ++ -> Geração de Código -> Biblioteca de Tempo de Execução

Examine todas as bibliotecas e veja se elas são compiladas da mesma maneira.

Mais sobre este erro neste link:

aviso LNK4098: defaultlib "LIBCD" entra em conflito com o uso de outras bibliotecas


Essa foi a razão do erro! Obrigado pela dica.
Rkachach

1
Esta é a melhor resposta para programadores menos experientes.
meolic

32

OMI este link de Yochai Timmer foi muito bom e relevante, mas doloroso de ler. Eu escrevi um resumo

Yochai, se você já leu isso, consulte a nota no final.


Para a postagem original, leia: aviso LNK4098: defaultlib "LIBCD" entra em conflito com o uso de outras bibliotecas

Erro

LINK: aviso LNK4098: defaultlib "LIBCD" entra em conflito com o uso de outras bibliotecas; use / NODEFAULTLIB: biblioteca

Significado

uma parte do sistema foi compilada para usar uma única biblioteca padrão encadeada (libc) com informações de depuração (libcd), que são vinculadas estaticamente

enquanto outra parte do sistema foi compilada para usar uma biblioteca padrão multiencadeada sem informações de depuração que residem em uma DLL e usam vínculo dinâmico

Como resolver

  • Ignore o aviso, afinal é apenas um aviso. No entanto, seu programa agora contém várias instâncias das mesmas funções.

  • Use a opção de vinculador / NODEFAULTLIB: lib. Esta não é uma solução completa, mesmo que você consiga vincular seu programa dessa maneira, você está ignorando um sinal de aviso: o código foi compilado para diferentes ambientes, parte do seu código pode ser compilado para um único modelo de encadeamento enquanto outro código é multiencadeado.

  • vasculhe todas as suas bibliotecas e garanta que elas tenham as configurações de link corretas

Neste último, como mencionado no post original, dois problemas comuns podem surgir:

  • Você tem uma biblioteca de terceiros que está vinculada diferentemente ao seu aplicativo.

  • Você tem outras diretivas incorporadas ao seu código: normalmente esse é o MFC. Se algum módulo do seu sistema estiver vinculado ao MFC, todos os módulos deverão vincular nominalmente à mesma versão do MFC.

Para esses casos, certifique-se de entender o problema e decidir entre as soluções.


Nota: Eu queria incluir esse resumo do link de Yochai Timmer em sua própria resposta, mas como algumas pessoas têm problemas para revisar as edições corretamente, tive que escrevê-lo em uma resposta separada. Desculpe


7

Recebo isso toda vez que desejo criar um aplicativo no VC ++.

Clique com o botão direito do mouse no projeto, selecione Propriedades e, em 'Propriedades da configuração | C / C ++ Code Generation ', selecione "Multi-threaded Debug (/ MTd)" para configuração de Debug.

Observe que isso não altera a configuração da sua versão do Release - você precisará ir para o mesmo local e selecionar "Multi-threaded (/ MT)" para o Release.


4

Clique com o botão direito do mouse no projeto, selecione Propriedades e, em 'Propriedades da configuração | Linker Entrada | Ignore a biblioteca específica e escreva msvcrtd.lib

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.