Ошибки от 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.