Ошибки от VC8 до VC10 - LNK2005

Недавно я установил Visual Studio 2010 и использовал CMake для создания файлов решений для моего проекта. Этот процесс ранее работал отлично на VS2005.

Первая проблема, с которой я столкнулась, связана с новыми "конструкторами перемещения", поэтому мне пришлось удалить некоторые неявные преобразования из моего кода — справедливо, что работает сейчас.

Моя текущая ситуация выглядит следующим образом: Я компилирую DLL 1, которая зависит только от некоторых системных библиотек (Kernel32 и т.д.) и CRT, а DLL 2, который ссылается на DLL 1, а также на некоторые сторонние библиотеки.

Ошибки, которые я получаю, соответствуют строкам:

DLL1.lib(DLL1.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" ([email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]) already defined in objFromDLL2.obj

Это, по-видимому, проблема, описанная здесь здесь.

Однако ничто в этой теме не решает мою проблему.

  • Я подтвердил, что как DLL1, так и DLL2 скомпилированы с флагом генерации кода MD,
  • DLL2 ссылки на squish, glew и devil — Я вручную перекомпилировал все эти и любые библиотеки, на которые они зависят, для VC10, также с /MD
  • изменить. эта статья (похожа на мою проблему), я удалил все экземпляры классов вывод из std:: container
  • изменить Я подтвердил, что это не проблема третьей стороны, поскольку я скомпилировал другой проект с использованием одного и того же набора библиотек, однако я до сих пор не могу скомпилировать свой оригинальный проект
  • edit dllexport используется во всех необходимых местах в моем коде

Что мне не хватает? Пожалуйста, дайте мне знать, если мне нужно предоставить дополнительную информацию, и я отредактирую вопрос как можно лучше.

update: Это было какое-то время, и у меня все еще нет решения. Я обновляю вопрос с ответами на комментарии, и сейчас я работаю над другой базой кода, которая действительно работает. Я начинаю думать, что обратная совместимость для более старого кода, наконец, начала высыхать, и я должен просто двигайтесь дальше.

больше обновлений: я обнаружил, что, вероятно, очень нежелательный флаг компоновщика /FORCE: MULTIPLE, который превращает ошибки в предупреждения, игнорируя все, кроме первого определения символов. Это должно быть плохим побочным эффектом. Тест этого флага выделил LNK2001: неразрешенный std::string:: npos, который был похоронен во всех предыдущих ошибках LNK2005. Мучения никогда не заканчиваются.

Ответ 1

Я успешно использовал /FORCE:MULTIPLE. Иногда это неизбежно при использовании смешанного пакета библиотек. Пока компоновщик использует один и тот же адрес для последовательного разрешения ссылки, он работает. Другие определения игнорируются.

Ответ 2

Я склонен думать, что ваши высказанные предположения неверны. В частности, "DLL 1, зависящая только от некоторых системных библиотек (Kernel32 и т.д.)", Не может быть прав, если она скомпилирована с /MD и относится к std::string::~string. Это, очевидно, вызовет зависимость от ЭЛТ.

Асло, если DLL1 не зависит от DLL2, как в мире является компоновщик, знакомый с файлами из DLL2?! Удалось ли вам установить циклическую зависимость?

Между VS2008 и VS2010, кажется, что std::string::~string был удален из CRT. Поэтому он больше не DLLimport для вашего собственного кода. Это может объяснить разницу в поведении. Циклическая зависимость между DLL1 и DLL2 не имела бы значения std::string::~string, поскольку оба могли бы получить ее из CRT и, очевидно, не были бы частью цикла.

Ответ 3

Похоже, проблема в том, что DLL1 экспортирует std::string (вероятно, неявно, потому что он используется в классе, который также экспортируется), но заголовки DLL1 не объявляют об этом. Поэтому, когда DLL2 скомпилирован, он не отмечен как импорт. Это не проблема, потому что это шаблон: компилятор просто создает экземпляр другой копии. Но затем компоновщик спотыкается, потому что DLL2 действительно должен был импортировать std::string.

Решение: явно экспортировать/импортировать std::string; у вас, вероятно, уже есть соответствующий макрос для _declspec( ) в заголовке (ей) DLL1.