Обнаружено несоответствие для RuntimeLibrary

114

Я загрузил и извлек Crypto ++ в C: \ cryptopp. Я использовал Visual Studio Express 2012 для сборки всех проектов внутри (как указано в readme), и все было построено успешно. Затем я сделал тестовый проект в какой-то другой папке и добавил cryptolib в качестве зависимости. После этого я добавил путь включения, чтобы я мог легко включить все заголовки. Когда я пытался скомпилировать, у меня возникла ошибка о неразрешенных символах.

Чтобы исправить это, я добавил C:\cryptopp\Win32\Output\Debug\cryptlib.libссылки на дополнительные зависимости. Теперь я получаю такую ​​ошибку:

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

Я также получаю:

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

Код, который я пытался скомпилировать, был прост (я получил его с другого сайта):

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

Любые идеи, как это исправить? Мне сейчас действительно нужен только SHA-256, больше ничего. Я использую 64-разрядную версию Windows 7, и сегодня я скачал VS C ++, так что это должна быть самая новая версия.

Momonga
источник
1
Я установил библиотеку времени выполнения своего проекта на многопоточную отладку (это была настройка, используемая в crypto ++), и теперь она компилируется! :) Огромное спасибо.
Момонга
Проблемы возникли намного раньше, когда вы бежали VCUpgrade. Вы видите симптомы сбоя VCUpgrade, о котором вам сообщили как об успехе .
jww

Ответы:

234

(На этот вопрос уже есть ответ в комментариях, но поскольку фактического ответа на него нет , я пишу это.)

Эта проблема возникает в более новых версиях Visual C ++ (более старые версии обычно просто связывали программу без уведомления, и она вылетала из строя и сгорала во время выполнения.) Это означает, что некоторые библиотеки, которые вы связываете с вашей программой (или даже некоторые из исходных кодов файлы внутри самой программы) используют разные версии CRT (библиотека C RunTime.)

Чтобы исправить эту ошибку, вам нужно зайти в свою Project Properties(и / или те из библиотек, которые вы используете), затем в C/C++, затем Code Generationи проверить значение Runtime Library; это должно быть одинаково для всех файлов и библиотек, которые вы связываете вместе. (Правила для связывания с библиотеками DLL немного более мягкие, но я не собираюсь здесь вдаваться в «почему» и более подробно.)

В настоящее время существует четыре варианта этого параметра:

  1. Многопоточная отладка
  2. Многопоточная DLL отладки
  3. Многопоточный выпуск
  4. DLL многопоточного выпуска

Ваша конкретная проблема, похоже, связана с тем, что вы связали библиотеку, созданную с помощью «Многопоточной отладки» (т. Е. Статической многопоточной отладочной CRT), с программой, которая создается с использованием параметра «Многопоточная отладка DLL » (то есть динамической многопоточной отладочной CRT). Вы должны изменить этот параметр либо в библиотеке, либо в вашей программе. А пока я предлагаю изменить это в вашей программе.

Обратите внимание, что, поскольку проекты Visual Studio используют разные наборы параметров проекта для отладочных и выпускных сборок (и 32/64-разрядных сборок), вы должны убедиться, что параметры совпадают во всех этих конфигурациях проекта.

Для (некоторой) дополнительной информации вы можете увидеть это (ссылка на комментарий выше):

  1. Предупреждение средств компоновщика LNK4098 в MSDN
  2. / MD, / ML, / MT, / LD (использовать библиотеку времени выполнения) в MSDN
  3. Ошибки сборки с VC11 Beta - смешивание библиотек MTd с exes MDd не удается связать в Bugzilla @ Mozilla

ОБНОВЛЕНИЕ : (Это ответ на комментарий, в котором спрашивается, почему нужно проявлять такую ​​осторожность.)

Если два фрагмента кода, которые мы связываем вместе, сами связываются со стандартной библиотекой и используют ее, то стандартная библиотека должна быть одинаковой для них обоих, если не уделяется особого внимания тому, как наши две части кода взаимодействуют и передают данные. Как правило, я бы сказал, что почти для всех ситуаций просто используйте одну и ту же версию среды выполнения стандартной библиотеки (в отношении отладки / выпуска, потоков и, очевидно, версии Visual C ++, среди прочего, таких как отладка итератора и т. Д.)

Самая важная часть проблемы заключается в следующем: иметь одинаковое представление о размере объектов по обе стороны от вызова функции .

Рассмотрим, например, что два вышеуказанных фрагмента кода называются Aи B. A скомпилирован для одной версии стандартной библиотеки, а B - для другой. В представлении A некоторый случайный объект, который ему возвращает стандартная функция (например, блок памяти, итератор, FILEобъект или что-то еще), имеет определенный размер и макет (помните, что макет структуры определяется и фиксируется во время компиляции в C / C ++.) По любой из нескольких причин представление B о размере / расположении одних и тех же объектов отличается (это может быть из-за дополнительной отладочной информации, естественной эволюции структур данных с течением времени и т. Д.)

Теперь, если A вызывает стандартную библиотеку и возвращает объект, затем передает этот объект B, а B каким-либо образом касается этого объекта, есть вероятность, что B испортит этот объект (например, напишет неправильное поле или пропустит конец этого и т. д.)

Вышеупомянутые проблемы - не единственные, которые могут возникнуть. Внутренние глобальные или статические объекты в стандартной библиотеке также могут вызывать проблемы. Есть и более неясные классы проблем.

Все это становится еще более странным в некоторых аспектах при использовании DLL (динамической библиотеки времени выполнения) вместо библиотек (статической библиотеки времени выполнения).

Эта ситуация может применяться к любой библиотеке, используемой двумя частями кода, которые работают вместе, но стандартная библиотека используется большинством (если не почти всеми) программами, и это увеличивает шансы конфликта.

То, что я описал, очевидно, является разбавленной и упрощенной версией фактического беспорядка, который ждет вас, если вы смешаете версии библиотек. Надеюсь, это даст вам представление о том, почему вам не следует этого делать!

yzt
источник
Я немного смущен. Ошибка OP - LNK2038 . Поскольку это происходит не со всеми библиотеками, я подозреваю, что Crypto ++ играет с некоторыми настройками CRT, которые делают невозможным смешивание вкусов CRT - обычно это просто предупреждение (LNK4098), и вы можете быть в безопасности, если знаете, что делаете (не рекомендуется, но возможно с ограничениями, см., например, stackoverflow.com/a/19944935/948581 ). Однако я не знаю, почему Crypto ++ страдает таким образом.
1
@Tibo: это не библиотеки импорта для DLL; Я считаю, что Crypto ++ на самом деле статически связан с программой здесь. Это означает, что любое несоответствие в стандартной библиотеке, связываемой в одном модуле с другим (вероятно), нарушает «одно правило определения». Что плохо. Раньше это не было ошибкой, поскольку компоновщик даже не мог это обнаружить (имена функций / типов были одинаковыми, но их тела и определения значительно различались) до VC10, когда компоновщик / библиотекарь начал «помечать» модули он производит дополнительную информацию о конфигурации сборки ...
yzt 03
@Tibo: ... (продолжение предыдущего комментария) Например, посмотрите на первый блок ошибок, о котором сообщает OP. Там « RuntimeLibrary » - это тег как библиотеки Crypto ++, так и объектного файла для программы OP, и его значение - « MDd_DynamicDebug » для одного из них и « MTd_StaticDebug » для другого. Таким образом, компоновщик, который пытается связать два объектных файла вместе, может обнаруживать и сообщать о совершенно новом классе ошибок, учитывая, что компоновщики, создавшие эти объектные файлы, пометили их любой соответствующей информацией, особенно любыми настройками, которые потенциально могут нарушить ODR.
yzt 03
Хотя я полностью с вами согласен, здесь все еще есть область загадки. Что касается проблемы OP, я предполагаю, что он включает "dll.h" из Crypto ++, а затем пытается связать со статической библиотекой вместо библиотеки импорта DLL. Но я видел точно такие же ошибки на одном компьютере, а не на другом (VS2013 ultimate sp4 -> error, VS2013 community sp5 -> ok) ...
1
@yzt Я нашел решение. Вместо использования / ZW swicth Windows предоставляет способ использования WinRT API через COM с помощью оболочки под названием WRL. Просто отсутствие использования / ZW делает кодирование немного сложным, поскольку скрывает детали реализации COM, но можно использовать WinRT без / ZW.
Сахил Сингх
3

Я загрузил и извлек Crypto ++ в C: \ cryptopp. Я использовал Visual Studio Express 2012 для сборки всех проектов внутри (как указано в readme), и все было построено успешно. Затем я сделал тестовый проект в какой-то другой папке и добавил cryptolib в качестве зависимости.

Возможно, преобразование не было успешным. Единственное, что было успешным, - это запуск VCUpgrade. Само преобразование не удалось, но вы не узнаете об этом, пока не столкнетесь с обнаруженными вами ошибками. Некоторые подробности см. В Visual Studio на вики-странице Crypto ++.


Любые идеи, как это исправить?

Чтобы решить ваши проблемы, вы должны загрузить, vs2010.zipесли вы хотите статическое связывание среды выполнения C / C ++ ( /MTили /MTd), или vs2010-dynamic.zipесли вы хотите динамическое связывание среды выполнения C / C ++ ( /MTили /MTd). Оба исправляют скрытые, тихие сбои, производимые VCUpgrade.


vs2010.zip, vs2010-dynamic.zipи vs2005-dynamic.zipсозданы из последних исходников GitHub . На момент написания этой статьи (1 июня 2016 г.) это фактически pre-Crypto ++ 5.6.4. Если вы используете ZIP-файлы с более низким уровнем Crypto ++, например 5.6.2 или 5.6.3, вы столкнетесь с небольшими проблемами.

Мне известны две незначительные проблемы. Во-первых, это переименование bench.cppвbench1.cpp . Его ошибка:

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

Чтобы исправить это, либо (1) откройте cryptest.vcxprojв блокноте, найдите bench1.cppи переименуйте его в bench.cpp. Или (2) переименовать bench.cppв bench1.cppв файловой системе. Пожалуйста, не удаляйте этот файл.

Вторая проблема немного сложнее, потому что это движущаяся цель. В выпусках нижнего уровня, таких как 5.6.2 или 5.6.3, отсутствуют последние классы, доступные в GitHub . К отсутствующим файлам классов относятся HKDF (5.6.3), RDRAND (5.6.3), RDSEED (5.6.3), ChaCha (5.6.4), BLAKE2 (5.6.4), Poly1305 (5.6.4) и т. Д.

Исправление состоит в том, чтобы удалить отсутствующие исходные файлы из файлов проекта Visual Studio, поскольку они не существуют для выпусков более низкого уровня.

Другой вариант - добавить недостающие файлы классов из последних источников, но могут возникнуть сложности. Например, многие из источников тонко зависят от последней config.h, cpu.hи cpu.cpp. «Тонкость» в том, что вы не поймете, что у вас недостаточно эффективный класс.

Примером неэффективного класса является BLAKE2. config.hдобавляет время компиляции ARM-32 и обнаружение ARM-64. cpu.hи cpu.cppдобавляет обнаружение инструкций ARM во время выполнения, которое зависит от обнаружения времени компиляции. Если вы добавите BLAKE2 без других файлов, то обнаружение не произойдет, и вы получите прямую реализацию C / C ++. Вы, вероятно, не поймете, что упускаете возможность NEON, которая работает от 9 до 12 циклов на байт по сравнению с 40 циклами на байт или около того для ванильного C / C ++.

jww
источник
Я следовал инструкциям в вики-сайте cryptopp, скачал vs2010-dynamic.zip и вставил его содержимое в код cryptopp563. Создан, и некоторые исходные файлы отсутствуют. Нет проблем, в вики говорится, что zip предназначен для последнего проекта на github, и просто удалите все отсутствующие файлы. Удаленные. Теперь проект просто не строится: 4 ошибки ссылок, один пример: ошибка LNK2001: неразрешенный внешний символ «void __cdecl OutputResultOperations (char const *, char const *, bool, unsigned long, double)» (? OutputResultOperations @@ YAXPBD0_NKN @ Z)
Янив
Оказалось, что в проекте отсутствовал файл bench.cpp. Но даже после этого он не компилировался, пока я не применил это исправление к fiptest.cpp github.com/weidai11/cryptopp/pull/151/files?diff=split, я бы хотел, чтобы они сделали в этом какой-то порядок, например, добавили zip-файлы проекта в git или что-то в этом роде. И да, я забыл сказать, что мой компилятор - это обновление VS2015 2. В итоге, следуйте подсказкам, которые я написал, и он работает.
Янив
@Yaniv - Что вы посоветуете для первого комментария, чтобы другие пользователи не испытывали проблем? Что касается второго комментария, мы планируем использовать патч, как только мы его полностью протестируем. Что мы можем пока сделать? (Я добавил к этому ответу дополнительную информацию, но хочу, чтобы у пользователей не было проблем).
jww 01
Во-первых, большое спасибо за это. Crypto ++ действительно потрясающий. Что касается проблем сборки, постарайтесь, чтобы файлы sln и проекта Windows были совместимы с последними файлами в проекте, и, поскольку эти изменения, конечно, изменяются, эта сборка Windows должна быть каким-то образом связана с базой кода и, возможно, даже находиться в дереве исходных текстов. Если это слишком много, по крайней мере, убедитесь, что zip-файл со средой сборки Visual Studio совместим с текущим стабильным официальным выпуском.
Янив
Что касается патча для fiptest.cpp - похоже, что-то другое в VS2015, поэтому я думаю, что любой, кто хочет использовать VS2015, должен применить этот патч. Это просто еще один случай в блоке #ifdef, который, кажется, определяет правильный обратный вызов отладки для VS2015, и его действительно легко исправить вручную.
Янив
3

У меня была эта проблема вместе с несоответствием в ITERATOR_DEBUG_LEVEL. Поскольку воскресная и вечерняя проблема все-таки казалась нормальной и подходящей для решения, я на какое-то время отключился. Работая в IDE VS2017 (обозреватель решений), я недавно добавил / скопировал ссылку на исходный файл в свой проект (перетаскивание с помощью Ctrl) из другого проекта. Заглянув в свойства-> C / C ++ / Preprocessor - на уровне исходного файла, а не на уровне проекта - я заметил, что в конфигурации выпуска _DEBUG был указан вместо NDEBUG для этого исходного файла. Это было все, что нужно было изменить, чтобы избавиться от проблемы.

январь
источник
1

Проблема может быть решена путем добавления CRT файла msvcrtd.lib в библиотеку компоновщика. Потому что cryptlib.lib использует версию отладки CRT.

abhijithkp
источник