- узнать, какая из двух библиотек вам действительно нужна
- узнайте, как рассказать компоновщику не использовать другой (используя, к примеру, отзыв от Джеймса Хопкина).
xtofl 05 дек. 2008, в 11:19
Поделиться
+1 Хороший вопрос — я не совсем правильно прочитал ошибку. У меня недавно была похожая ошибка компоновщика, когда опция библиотек MFC загадочным образом включилась.
James Hopkin 05 дек. 2008, в 11:20
Точное объяснение. Спасибо за это. 🙂
mahesh 05 дек. 2008, в 11:41
Отсутствует детализация — некоторые библиотеки определяют слабые связи, при определении правильного порядка включения библиотеки сначала будет использоваться mfc, а затем — msvcrt, и поэтому тихо отбрасывает слабую связь
Greg Domjan 19 сен. 2012, в 16:09
Показать ещё 1 комментарий
У меня было такое же сообщение об ошибке, но ни один из ответов здесь не разрешил для меня. Поэтому, если вы столкнулись с этой проблемой при создании DLL-проекта, который использует MFC, его можно решить, введя следующую строку:
How to Fix Include Path Error in C/C++ Files using Visual Studio Code
extern «C»
в файл cpp, где DllMain определен. Затем используется ваша собственная реализация DllMain , а не одна из dllmain.obj.
Когда мы пытаемся использовать библиотеку MFC, мы обязательно включим afx.h напрямую или косвенно, то MFC (afx.h) сообщает компоновщику, чтобы найти символ __afxForceUSRDLL и поместите этот объект, который содержит __afxForceUSRDLL в программу, поэтому линкер выполняет поиск и помещает dllmodule.obj в наш потому что __afxForceUSRDLL определяется в dllmodule.cpp.
Это общий сценарий. Когда мы хотим использовать наш собственный DllMain в mfc dll project, компоновщик жалуется, что есть два DllMain, один в наш код, один в Dllmodule.obj.
Итак, нам нужно сказать компоновщику, чтобы добавить наш dllmain.obj для __afxForceUSRDLL. Поэтому нам нужно определить __afxForceUSRDLL в нашем собственном файле cpp, где определен наш собственный DllMain, тогда компоновщик будет игнорировать mfcs dllmodule.obj и видеть только один DllMain и никогда не жалуется.
Constantin 12 нояб. 2013, в 14:33
Поделиться
Grant 13 нояб. 2013, в 04:39
работал для меня, я использую VS2010.
zhaorufei 19 фев. 2014, в 04:59
Отлично . у меня это тоже сработало. Спасибо за совет.
jaklucky 03 март 2014, в 17:23
Работал как шарм . от этой ошибки всегда трудно избавиться. Большое спасибо.
Ram 06 июнь 2014, в 06:51
Большое спасибо, это действительно помогло. Я получал сообщение об ошибке для extern «C» в VS2015, поэтому я добавил #define перед ним, и теперь он работает как шарм 🙂
user4710450 17 янв. 2016, в 17:41
Работал для меня с VS2008 и DLL, где я вызвал ошибку соединения, используя коллекции MFC, в частности CMapStringToString.
osullivj 09 фев. 2016, в 17:00
Я удалил //AFX_MANAGE_STATE(AfxGetStaticModuleState()); stackoverflow.com/a/9070135/1641556
Elshan 19 апр. 2016, в 06:29
Для кода, который должен компилироваться как 32-битный и 64-битный, используйте этот #ifdef X86 extern «C» #else extern «C» #endif
LNK2019
JonDrnek 02 янв. 2018, в 18:57
Anurag S Sharma 22 май 2018, в 08:33
Показать ещё 7 комментариев
Если вы определяете свой собственный DllMain, в настройках вашего проекта вам нужно установить «Использовать MFC» в «Свойства конфигурации/Общие» для «Использовать стандартные библиотеки Windows».
Вы должны сделать чистую перестройку после ее изменения.
James Hopkin 05 дек. 2008, в 10:40
Поделиться
У меня есть чистая C, не MFC DLL, установленная на «Использовать стандартные библиотеки Windows», но ошибка все еще появляется.
Timothy Gu 15 март 2015, в 23:58
Я тоже. VS2010.
AlastairG 26 янв. 2018, в 14:52
Я обнаружил, что удаление _WINDOWS из препроцессора определяет в настройках проекта -> C / C ++ -> Препроцессор избавился от ложной ссылки на MSVCRTD.lib. Я использую VS2010.
ulatekh 28 фев. 2018, в 21:29
Показать ещё 1 комментарий
Для меня прямая причина была действительно отсутствующей ссылкой на символ _afxForceUSRDLL, но косвенной причиной было отсутствие определения макроса _USRDLL. Он определяется по умолчанию мастером VC, но иногда разработчики стирают его ошибочно. Вот несколько слов.
Ofek Shilon 06 май 2015, в 05:49
Поделиться
У меня было наоборот! У меня был мошенник _USRDLL в препроцессоре, который должен был быть _LIB. Doh!
TinyRacoon 31 март 2016, в 09:47
В моем проекте я смог решить эту проблему, добавив mfcs80.lib и msvcrt.lib в качестве дополнительных зависимостей в настройках проекта. «Дополнительные зависимости» можно найти в Linker → Input.
В конфигурации отладки, которая должна быть mfcs80d.lib и msvcrtd.lib соответственно.
Кстати, я работаю с Visual Studio 2010, поэтому в моем случае MFC lib называется mfc100.lib.
Я не уверен, почему это сработало. Нет необходимости добавлять эти файлы lib в качестве дополнительных зависимостей, потому что я уже установил «Использование MFC» в «Использовать MFC в общей DLL». Я предполагаю, что, указав эти библиотеки в качестве дополнительных зависимостей, они связаны в другом порядке.
Это решение более или менее совпадает с тем, которое предлагается на сайте Microsoft: http://support.microsoft.com/kb/148652, за исключением того, что мне не нужно вводить все в поле «Игнорировать конкретные библиотеки по умолчанию».
vmb100 05 июль 2012, в 13:59
Поделиться
Ссылка, которую вы предложили, помогла мне найти решение. Стоит прочитать.
TinyRacoon 31 март 2016, в 09:06
Для всех тех, кто испытывает эту ошибку в проектах ATL (в основном при попытке добавить поддержку MFC), вот решение, которое я нашел после нескольких дней разочарования!
Прежде всего, эта ссылка была для меня более полезной, чем все остальные. Он указал мне в правильном направлении. Проблема возникает, если по какой-то причине «сгенерированные файлы» (содержащие прокси-сервер и код-заглушки, так же как и типы) были удалены и прочитаны в проекте. Это заставляет Visual Studio добавлять их в неправильном порядке!
Обычно вы сначала сталкиваетесь с ошибкой «ATL требует компиляции С++», но вы можете исправить это, отключив параметр Yc/Yu (предварительно скомпилированные заголовки) для этого файла.
Что вы должны сделать дальше, это разгрузить проект и отредактировать его. Найдите группы товаров, которые определяют порядок сборки и включают порядок ( ClCompile и ClInclude ). Проверьте их порядок и настройки.
Компиляторы должны отображаться в следующем порядке:
- dllmain.cpp (с CompileAsManaged установлено значение false и PrecompiledHeader осталось пустым).
- Источник библиотеки ( MyLib.cpp , содержащий DllCanUnloadNow и т.д.)
- Код прокси-сервера ( MyLib_i.c ; с теми же настройками, что и dllmain.cpp )
- stdafx.cpp (с PrecompiledHeader установлено значение Create )
- Все остальные исходные файлы библиотеки (фактическое содержимое библиотек)
- xdlldata.c (с теми же настройками, что и dllmain.cpp )
Затем заказы должны быть упорядочены следующим образом:
- dllmain.h
- MyLib_i.h
- Resource.h
- stdafx.h
- targetver.h
- . (фактические заголовки библиотек)
- xdlldata.h
Фиксирование порядка сборки зафиксировал мой проект, и я смог создать новую чистую сборку.
Carsten 13 янв. 2015, в 10:19
Поделиться
Просто хотел прокомментировать, что этот ответ был чрезвычайно полезен; Я не знал, что компоновщик зависел от порядка включения компоновки в проекте, но на самом деле это решило проблему для меня.
Nick 31 окт. 2016, в 18:21
Идентификатор базы знаний MSDN Q148652.
Причина: Visual С++ компилирует исходные файлы в алфавитном порядке и передает скомпилированные объектные файлы в компоновщик в алфавитном порядке. Если компоновщик сначала обрабатывает DLLDATAX.OBJ, исходный код ссылается на DllMain, который компоновщик загружает из MSVCRTD.LIB(dllmain.obj). Затем компоновщик обрабатывает объектный файл, скомпилированный из файла С++, который содержит #include «stdafx.h», который ссылается на символ __afxForceUSRDLL, который компоновщик загружает из MFC42D.LIB(dllmodul.obj). Этот объектный модуль также содержит реализацию для DllMain, вызывая конфликт.
Источник: overcoder.net
Ошибка средств компоновщика LNK2005
За этой ошибкой следует Неустранимая ошибка LNK1169.
Возможные причины и решения
Как правило, эта ошибка означает, что вы нарушили одно правило определения, которое допускает только одно определение любого используемого шаблона, функции, типа или объекта в данном объектном файле и только одно определение во всем исполняемом объекте для внешних видимых объектов или функций.
Ниже приведены некоторые распространенные причины этой ошибки.
- Эта ошибка может возникать, когда заголовочный файл определяет переменную. Например, если включить этот файл заголовка в более чем один исходный файл в проекте, возникает ошибка:
// LNK2005_global.h int global_int; // LNK2005
- Объявите переменную extern в файле заголовка: extern int global_int; , затем определите ее и при необходимости инициализируйте ее в одном и только одном исходном файле: int global_int = 17; . Теперь эта переменная является глобальной, которую можно использовать в любом исходном файле путем объявления ее extern , например, путем включения файла заголовка. Мы рекомендуем использовать это решение для переменных, которые должны быть глобальными, но хорошей практикой разработки программного обеспечения является сокращение числа глобальных переменных.
- Объявите переменную static: static int static_int = 17; . Это ограничивает область определения текущим объектным файлом и позволяет нескольким файловым файлам иметь собственную копию переменной. Не рекомендуется определять статические переменные в файлах заголовков из-за возможности путаницы с глобальными переменными. Предпочитают перемещать определения статических переменных в исходные файлы, которые их используют.
- Объявите переменную selectany: __declspec(selectany) int global_int = 17; . Это предписывает компоновщику выбрать одно определение для использования всеми внешними ссылками и отменить остальные. Это решение иногда полезно при объединении библиотек импорта. В противном случае мы не рекомендуем использовать его как способ избежать ошибок компоновщика.
// LNK2005_func.h int sample_function(int k) < return 42 * (k % 167); >// LNK2005
- inline Добавьте ключевое слово в функцию:
// LNK2005_func_inline.h inline int sample_function(int k)
// LNK2005_func_decl.h int sample_function(int);
// LNK2005_func_impl.cpp int sample_function(int k)
// LNK2005_member_outside.h class Sample < public: int sample_function(int); >; int Sample::sample_function(int k) < return 42 * (k % 167); >// LNK2005
Чтобы устранить эту проблему, переместите определения функций члена внутри класса. Функции-члены, определенные внутри объявления класса, неявно встроены.
// LNK2005_member_inline.h class Sample < public: int sample_function(int k) < return 42 * (k % 167); >>;
oledb.lib(oledb_i.obj) : error LNK2005: _IID_ITransactionObject already defined in uuid.lib(go7.obj)
Источник: code-live.ru
Какие #includes в main.cpp следует использовать (LNK2005 уже определен)
Когда я запускаю свою программу, я получаю следующие ошибки:
Я думаю, это связано с тем, что в main.cpp я пишу #include «Buffer.cpp», но я не знаю, как это сделать без этого #include. Как я могу использовать объекты Buffer, если я не есть это #include?
crende 4 Ноя 2016 в 14:01
Вы правы в том, где проблема. Включить buffer.h вместо buffer.cpp ? В файле .cpp требуется только объявление типов/функций, определение может быть в отдельном файле.
4 Ноя 2016 в 14:04
Martin Bonner supports Monica
4 Ноя 2016 в 14:06
Вам не нужно объявлять WAV_HEADER — вам нужно определить его (#включая buffer.h).
Martin Bonner supports Monica
4 Ноя 2016 в 15:07
3 ответа
Главное должно начаться
#include «Buffer.h»
Так что у него есть определение класса (но не определение всех функций-членов). Вы почти никогда не хотите #include файлы .cpp.
Это приведет к дальнейшим ошибкам, потому что вы используете типы в Buffer.h, которые вы там не определили. Исправление для этого состоит в том, чтобы определить их, поместив
#include «MonoSample.h»
В начале Buffer.h.
Martin Bonner supports Monica 4 Ноя 2016 в 15:09
Я бы сказал никогда не включать файлы .cpp. «Почти» добавляет много смысла.
4 Ноя 2016 в 14:05
Существуют продвинутые методы препроцессора, которые включают в себя включаемые исходные файлы. Один из подходов — называть их файлами .inl. Другой вариант — называть их .cpp (что означает, что ваш редактор их понимает).
Martin Bonner supports Monica
4 Ноя 2016 в 14:08
Источник: question-it.com
Русские Блоги
Язык C: ошибки и решения LNK2005 и LNK1169 из-за #include * .c / .cpp в среде VS
Язык C: ошибки и решения LNK2005 и LNK1169 из-за #include в среде VS
- Предисловие (пропускается)
- описание проблемы
- Альтернативный метод (пропускаемый)
- Метод слияния
- исключение
Предисловие (пропускается)
Сегодня, когда пишу программу обработки данных, так как количество строк кода влияет на чтение и запись, я хочу переместить некоторые основные функции обработки в другой файл. Идеал очень полный, реальность очень тонкая, я переместил некоторые функции из a.cpp (псевдоним) в b.cpp (псевдоним), затем добавил #include в начале a.cpp и соответствующий extern Имя функции (переменная); После отладки она сразу пошла не так, соответственно LNK2005 и LNK1169. После долгой проверки я не обнаружил никаких ошибок, и повторных определений переменных не было.
описание проблемы
Ссылка на файл содержит #include , а указанный файл содержит функции. При компиляции компилятор выдавал ошибки LNK2005 и LNK1169. Функция была определена в * .obj, и был найден один или несколько символов с несколькими определениями.
Часть программы:
Прямая цитата (включая) .c или .cpp файлы
И оба находятся в одном проекте(ерунда)
И есть функция во включенном файле
Часть ошибки компилятора:
Альтернативный метод (пропускаемый)
Нет необходимости искать какие-либо переменные или функции, которые не определены повторно в каждом файле.Нет, с того момента, как вы непосредственно ссылаетесь на файл .cpp или .c, содержащий функцию, ошибка уже обречена. Позвольте мне представить несколько более удобных (низко) альтернативных решений. Читатели, которые хотят напрямую обратиться к эффективным решениям, могут пропустить эти два метода.
Метод слияния
Очень просто, просто скопируйте код файла для включения вместо #include , где он был изначально, верно, не забудьте удалить включенный файл (или удалить его из решения Кроме)
Отладка пройдена, это удивительно.
Это простой метод проверки наличия дублированных объявлений или определений.Если в коде после выполнения этого шага все еще есть ошибки LNK2005 и LNK1169, это означает, что в вашем коде есть повторяющиеся объявления или определения, в противном случае нет дублирующих объявлений или определений. проблема. Дублирование всегда невозможно, после объединения в один файл дублирование больше не существует, так что это показывает, что речь не идет о повторном объявлении или определении.
исключение
Этот метод проще, и включенный файл напрямую удаляется из решения, но #include не следует изменять, а файл не следует перемещать, например так:
Отладка также может проходить:
Это удивительно? Немного проблематично не открывать другой файл в том же окне управления ресурсами во время программирования.
анализ проблемы
После двух вышеупомянутых тестов мы заметили, что источник проблемы связан с двумя файлами в одном решении. И когда код двух файлов помещается в один и тот же файл, ссылка на компиляцию не выдаст ошибку. так чтоОшибка связана с обработкой #include .И не имеет ничего общего с функцией самого кода.
На языке C #include будет вставлять указанный файл в исходный файл, Это эквивалентно нашему методу слияния.Однако при компиляции VS каждый файл .cpp или .c в решении будет компилироваться отдельно, только файл .h — нет. После компиляции в файл .obj VS связывает все файлы .obj вместе, чтобы создать файл .exe. Поэтому, если на a.cpp есть прямая ссылка на b.cpp, после компиляции будет сгенерирован a.obj, содержащий контент a + b, и b.obj, содержащий контент b. В это время, когда VS снова установит связь, вы обнаружите, что файл a.obj содержит повторяющиеся определения функций (или определения переменных) с b.obj, поэтому возникают ошибки LNK2005 и LNK1169.
Решение
Решение состоит в том, чтобы использовать ключевое слово extern, чтобы предложить компилятору найти свое определение в других файлах, когда он встречает эту переменную или функцию. Вместо непосредственного использования #include , такого как добавление объявления функции b.c в a.c: следующим образом:
extern bool Output_Structure(struct person* n); extern long Get_File_Size(FILE* File);
Затем вы можете использовать эти функции непосредственно в a.c. Если вам нужно использовать несколько файлов, вы можете поместить код объявления в файл заголовка, так что вам нужно только сослаться на файл заголовка.
Как показано на рисунке, ссылка на компиляцию прошла успешно.
Резюме и рефлексия
Должен быть разработан механизм, при котором файлы, вставленные во время компиляции, больше не будут компилироваться, но на самом деле мне нечего делать. Я всегда чувствую, что это решение приводит к тому, что длина кода становится больше, чем раньше, что серьезно влияет на производительность программы.В этом решении все еще есть много недостатков. Я надеюсь, что если у вас есть лучший способ оставить сообщение ниже, я отвечу вам в любое время. Спасибо.
Примечание. Согласно сообщению в блоге, что убийца из зыбучих песков отреагировал на ту же проблему, проблема также существует в VS6.0, и я получаю ошибку, созданную в среде VS2019,Следовательно, можно считать, что эта ошибка распространена во всей среде VS.
Примечание. После фактического тестирования файл #include также выдаст ту же ошибку, которая также может быть устранена тем же методом,Поэтому считается, что эта ошибка появится на языке Си / Си ++, и решение остается тем же.
Источник: russianblogs.com