Visual studio ошибка lnk2019

Обновлено: 07.07.2024

Редактирование

Index R source files - определяет, будут ли исходные файлы R в пределах Каталог проекта индексируется для навигации по коду (например, перейти к файлу / функции, перейти к определению функции). Обычно это должно оставаться включенным, однако, если у вас есть каталог проекта с тысячами файлов, и они обеспокоены накладными расходами на мониторинг и индексирование, вы можете отключить индексирование здесь. Insert spaces for tab . Определите, вставляет ли вкладка несколько пробелов, а не символ табуляции (мягкие вкладки). Настройте количество пробелов на одну вкладку. Text encoding - укажите текстовую кодировку по умолчанию для исходных файлов. Обратите внимание, что исходные файлы, которые не соответствуют кодировке по умолчанию, могут быть правильно открыты с помощью команды меню File : Reopen with Encoding . Источник

Компиляция программы на C ++ выполняется в несколько этапов, как указано в 2.2 (кредиты для Кейта Томпсона для ссылки) :

  1. Физические символы исходного файла сопоставляются в соответствии с реализацией в соответствии с базовым набором символов источника (ввод символов новой строки для индикаторов конца строки) при необходимости. [SNIP]
  2. Каждый экземпляр символа обратной косой черты (\), за которым сразу следует символ новой строки, удаляется, сплайсируя физические исходные строки для формирования логических строк источника. [SNIP]
  3. Исходный файл разбивается на токены предварительной обработки (2.5) и последовательности символов пробела (включая комментарии). [SNIP]
  4. Выполнены предпроцессорные директивы, макро-вызовы разворачиваются и выполняются операторные выражения _Pragma. [SNIP]
  5. Каждый элемент набора символов в символьном литерале или строковый литерал, а также каждая escape-последовательность и универсальное имя-символа в символьном литерале или не- -raw строковый литерал, преобразуется в соответствующий член набора символов выполнения; [SNIP]
  6. Соединительные маркеры литералов строки объединены.
  7. Символы пробела, разделяющие токены, уже не являются значимыми. Каждый токен предварительной обработки преобразуется в токен. (2.7). Результирующие маркеры синтаксически и семантически анализируются и переводятся как единица перевода. [SNIP]
  8. Устанавливаемые единицы перевода и единицы экземпляра объединяются следующим образом: [SNIP]
  9. Все ссылки на внешние сущности решена. Компоненты библиотеки связаны для удовлетворения внешних ссылок на объекты, не определенные в текущем переводе. Весь такой переводчик выводится в образ программы, который содержит информацию, необходимую для выполнения в среде выполнения. (акцент мой)

[footnote] Реализации должны вести себя так, как если бы эти отдельные фазы происходили, хотя на практике различные фазы могли быть свернуты вместе.

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

Скажите, что вы определили символ a в a.cpp . Теперь b.cpp объявил этот символ и использовал его. Перед связыванием он просто предполагает, что этот символ был определен где-то , но он пока не заботится о том, где. Фаза связывания отвечает за поиск символа и правильную привязку его к b.cpp (ну, собственно, к объекту или библиотеке, которая его использует).

Если вы используете Microsoft Visual Studio, вы будете см., что проекты генерируют файлы .lib . Они содержат таблицу экспортированных символов и таблицу импортированных символов. Импортированные символы разрешены против библиотек, на которые вы ссылаетесь, и экспортированные символы предоставляются для библиотек, которые используют этот .lib (если есть).

Подобные механизмы существуют для других компиляторов / платформ.

генерирует следующие ошибки с GCC:

и аналогичные ошибки с Microsoft Visual Studio:

. Общие причины включают в себя:

@MirroredFate есть способ улучшить VS Linker ошибки? Например, чтобы это выглядело скорее как gcc. – TankorSmash 4 December 2013 в 06:43 @TankorSmash Если только. Я думаю, что вы можете изменить выход с помощью этого , но я его не пробовал. – MirroredFate 4 December 2013 в 19:46 David Drysdale написал замечательную статью о том, как работают линкеры: Руководство для начинающих по компоновщикам . Учитывая тему этого вопроса, я подумал, что это может оказаться полезным. – Pressacco 22 May 2015 в 14:48

Что такое «неопределенный ссылочный / неразрешенный внешний символ»

Я попытаюсь объяснить, что такое «неопределенный ссылочный / неразрешенный внешний символ».

note : я использую g ++ и Linux, и все примеры для него

Например, у нас есть некоторый код

Создание объектных файлов

После фазы ассемблера у нас есть объектный файл, который содержит любые экспортируемые символы. Посмотрите на символы

Я отклонил некоторые строки из вывода, потому что они не имеют значения

Итак, мы видим следующие символы для экспорта.

src2.cpp ничего не экспортирует, и мы не видели его символов

Свяжите наши объектные файлы

и запустите его

Linker видит экспортированные символы и связывает их. Теперь мы пытаемся раскомментировать строки в src2.cpp, как здесь

, и перестроить объектный файл

OK (нет ошибок), потому что мы только строим объектный файл, связь еще не завершена. Попробуйте установить ссылку

Это произошло потому, что наше local_var_name статично, то есть оно не отображается для других модулей. Теперь глубже. Получить выход фазы перевода

i.e. вам должно быть как ниже

мы изменили видимость local_var_name и установили его значение в 456789. Попробуйте построить из него объектный файл

В настоящее время local_var_name имеет привязку GLOBAL (LOCAL)

ok, мы взломаем его:)

Итак, в результате - «неопределенная ссылка / неразрешенная внешняя ошибка символа» происходит, когда компоновщик не может найти глобальные символы в объектных файлах.

Отсутствует «extern» в объявлениях / определениях переменной const (только для C ++)

Для людей, прибывающих с C, может показаться неожиданным, что в C ++ глобальные переменные const имеют внутренние (или статические) связь. В C это не так, поскольку все глобальные переменные неявно extern (т.е. когда отсутствует ключевое слово static ).

correct would использовать файл заголовка и включить его в file2.cpp и file1.cpp

. В качестве альтернативы можно было бы объявить переменную const в файле file1.cpp с явным extern

Также, если вы используете сторонние библиотеки, убедитесь, что у вас есть правильные 32/64 битные файлы

Предположим, у вас есть большой проект, написанный на c ++, который содержит тысячу файлов .cpp и тысячу файлов .h. И давайте предположим, что проект также зависит от десяти статических библиотек. Скажем, мы работаем над Windows, и мы строим наш проект в Visual Studio 20xx. Когда вы нажимаете Ctrl + F7 Visual Studio, чтобы начать компиляцию всего решения (предположим, что у нас есть только один проект в решении)

В чем смысл компиляции?

Второй этап компиляции выполняется Linker.Linker должен объединить весь объектный файл и построить окончательно вывод (который может быть исполняемым или библиотекой)

Шаги по связыванию проекта

  • Разберите все объектные файлы и найдите определение, которое было объявлено только в заголовках (например: Код одного метода класса, как указано в p повторные ответы или событие инициализация статической переменной, которая является членом внутри класса)
  • Если один символ не может быть найден в объектных файлах, он также выполняется в дополнительных библиотеках. Для добавления новой библиотеки в project Свойства конфигурации -> Каталоги VC ++ -> Библиотечные каталоги, и здесь вы указали дополнительную папку для поиска библиотек и Свойства конфигурации -> Linker -> Input для указания имени библиотеки. -Если линкер не смог найти символ, который вы пишете в одном .cpp, он вызывает ошибку времени компоновщика, которая может звучать как error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)
  1. После того, как Linker найдет один символ, он не ищет в других библиотеках для него
  2. Порядок ссылок на библиотеки имеет значение.
  3. Если Linker находит внешний символ в одной статической библиотеке, он включает в себя символ на выходе проекта. Однако, если библиотека является общей (динамической), он не включает в себя код (символы) на выходе, но Run-Time могут возникнуть сбои

Как решить эту ошибку

Ошибка времени компилятора:

  • Убедитесь, что вы правильно выполнили синтаксический проект c ++.

Ошибка времени компоновщика

Разве ваш ответ не является специфическим для визуальной студии? В вопросе не указаны никакие инструменты IDE / компилятора, поэтому он делает ваш ответ бесполезным для части, не являющейся визуальной студией. – Victor Polevoy 13 August 2015 в 09:23 Ты прав . Но каждый процесс IDE в компиляции / компоновке выполняется немного по-другому. Но файлы обрабатываются точно так же (даже g ++ делает то же самое при анализе флагов ..) – user 13 August 2015 в 13:01 Проблема не в том, что касается IDE, а об ответе на проблемы с связыванием. Проблемы с связыванием не связаны с IDE, а с процессом компиляции и сборки. – Victor Polevoy 13 August 2015 в 13:02 Да. Процесс сборки / компоновки выполняется в g ++ / Visual Studio (компилятор, предоставленный Microsoft для VS) / Eclipse / Net Beans таким же образом – user 13 August 2015 в 13:06

Ошибки компоновщика могут произойти, если заголовочный файл и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.

Как работают линкеры? Линкер соответствует объявлению функции (объявленному в заголовке) с его определением (в общей библиотеке) путем сравнения их подписи. Вы можете получить ошибку компоновщика, если компоновщик не найдет определение функции, которое идеально подходит.

Возможно ли получить ошибку компоновщика, даже если объявление и определение, похоже, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете столкнуться с такой ситуацией:

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

Вы можете спросить, как это получается в такой ситуации? Включите пути, конечно! Если при компиляции разделяемой библиотеки путь include приводит к header1.h , и вы в конечном итоге используете header2.h в своей собственной программе, вы оставите царапины на своем заголовке, задаваясь вопросом, что произошло (каламбур).

Пример того, как это может произойти в реальном мире, объясняется ниже.

Дальнейшая разработка с примером

У меня есть два проекта: graphics.lib и main.exe . Оба проекта зависят от common_math.h . Предположим, что библиотека экспортирует следующую функцию:

И затем вы идете вперед и включаете библиотеку в свой собственный проект.

Boom! Вы получаете ошибку компоновщика, и вы понятия не имеете, почему она терпит неудачу. Причина в том, что общая библиотека использует разные версии одного и того же include common_math.h (я сделал это очевидным здесь в этом примере, включив другой путь, но это может быть не всегда так очевидно. Возможно, путь include отличается в настройки компилятора).

Обратите внимание, что в этом примере компоновщик сказал бы вам, что не смог найти draw() , когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли часами царапать себе голову, думая, что пошло не так. Дело в том, что компоновщик видит другую подпись, потому что типы параметров немного отличаются. В этом примере vec3 является другим типом в обоих проектах в отношении компилятора. Это может произойти из-за того, что они происходят из двух немного разных файлов include (возможно, включенные файлы поступают из двух разных версий библиотеки).

Отладка компоновщика

DUMPBIN - ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.

Процесс выглядит следующим образом:

  1. Обратите внимание на странное искаженное имя, указанное в ошибке компоновщика. (например, draw @ graphics @ XYZ).
  2. Выгрузите экспортированные символы из библиотеки в текстовый файл.
  3. Найдите экспортированный символ, представляющий интерес, и обратите внимание, что искаженное имя
  4. Обратите внимание на то, почему искаженные имена оказались разными. Вы могли бы видеть, что типы параметров различны, хотя они выглядят одинаково в исходном коде.
  5. Причина, почему они разные. В приведенном выше примере они различаются из-за разных файлов include.

[1] По проекту я имею в виду набор исходных файлов, которые связаны друг с другом для создания либо библиотеки, либо исполняемого файла .

РЕДАКТИРОВАТЬ 1: Переписать первый раздел, который будет легче понять. Пожалуйста, прокомментируйте ниже, чтобы сообщить мне, нужно ли что-то еще исправлять. Спасибо!

Обертка вокруг GNU ld, которая не поддерживает скрипты компоновщика

. Некоторые .so-файлы на самом деле являются GNU ld ссылками-компоновщиками , например. Файл libtbb.so является текстовым файлом ASCII с этим содержимым:

Некоторые более сложные сборки могут не поддерживать это. Например, если вы включаете -v в параметры компилятора, вы можете видеть, что mainwin gcc wrapper mwdip отбрасывает файлы команд сценария компоновщика в подробном списке результатов библиотек для ссылки. Простая работа вместо файла командной строки ввода сценария компоновщика вместо копии (или символической ссылки), например

Или вы можете заменить аргумент -l полным путем .so, например вместо -ltbb сделать /home/foo/tbb-4.3/linux/lib/intel64/gcc4.4/libtbb.so.2

Если все остальное не удается, перекомпилируйте.

Недавно я смог избавиться от нерешенной внешней ошибки в Visual Studio 2012, просто перекомпилировав нарушивший файл. Когда я перестроил, ошибка исчезла.

Это обычно происходит, когда две (или более) библиотеки имеют циклическую зависимость. Библиотека A пытается использовать символы в B.lib и библиотеке B пытается использовать символы из A.lib. Ничего не существует для начала. Когда вы пытаетесь скомпилировать A, шаг ссылки завершится неудачно, потому что он не может найти B.lib. A.lib будет сгенерирован, но не будет dll. Затем вы компилируете B, который будет успешным и сгенерирует B.lib. Повторная компиляция A теперь будет работать, потому что теперь найден B.lib.

Правильно - это происходит, когда библиотеки имеют циклическую зависимость. – Luchian Grigore 3 December 2013 в 22:51 Я расширил ваш ответ и связал его в главном. Благодарю. – Luchian Grigore 3 December 2013 в 22:56

Пакет Visual Studio NuGet необходимо обновить для новой версии набора инструментов

У меня просто возникла проблема с подключением libpng с Visual Studio 2013. Проблема в том, что в файле пакета были только библиотеки для Visual Studio 2010 и 2012.

Правильное решение - надеяться, что разработчик выпустит обновленный пакет и затем обновит его, но он работал для меня, взломав дополнительную настройку для VS2013, указав на файлы библиотеки VS2012.

Я отредактировал пакет (в папке packages внутри каталога решения), найдя packagename\build\native\packagename.targets и внутри этого файла, скопировав все секции v110 . Я изменил v110 на v120 в полях условий только очень осторожно, чтобы пути с именами файлов были все как v110 . Это просто позволило Visual Studio 2013 подключиться к библиотекам на 2012 год, и в этом случае он работал.

Это кажется чрезмерно специфичным - возможно, новый поток будет лучшим местом для этого ответа. – Luchian Grigore 17 January 2015 в 14:56 Этот вопрос уже имеет принятый ответ. Он отмечен как дубликат, потому что общая причина указана выше. Что произойдет, если бы у нас был ответ на каждый вопрос с библиотекой, которая не включена? – Luchian Grigore 17 January 2015 в 15:29

Невозможность связывания с соответствующими библиотеками / объектными файлами или компиляция файлов реализации

Обычно каждая единица перевода генерирует объектный файл, содержащий определения символов, определенных в этой единицы перевода. Чтобы использовать эти символы, вам необходимо связать эти объектные файлы.

В разделе gcc вы должны указать все объектные файлы, которые должны быть связаны вместе в командной строке, или скомпилировать файлы реализации вместе.

Здесь libraryName - это просто имя библиотеки, без добавления к платформе. Так, например, в файлах библиотеки Linux обычно называют libfoo.so , но вы должны писать только -lfoo . В Windows этот же файл можно назвать foo.lib , но вы будете использовать тот же аргумент. Возможно, вам придется добавить каталог, в котором эти файлы можно найти, используя -L‹directory› . Обязательно не записывайте пробел после -l или -L .

Для XCode: добавьте пути поиска заголовка пользователя -> добавьте путь поиска библиотеки -> перетащите фактическую ссылку библиотеки в

В MSVS файлы, добавленные в проект, автоматически связывают их объектные файлы, и будет создан файл lib (в общем использовании). Чтобы использовать символы в отдельном проекте, вам нужно будет добавить файлы lib в параметры проекта. Это делается в разделе Linker свойств проекта в Input -> Additional Dependencies . (путь к файлу lib должен быть добавлен в Linker -> General -> Additional Library Directories ). При использовании сторонней библиотеки, которая предоставляется с файлом lib , отказ в этом обычно приводит к ошибке.

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

В программировании Windows контрольный знак, который вы не связывали необходимая библиотека состоит в том, что имя неразрешенного символа начинается с __imp_ . Посмотрите имя функции в документации, и она должна сказать, какую библиотеку вам нужно использовать. Например, MSDN помещает информацию в поле внизу каждой функции в разделе «Библиотека».

Объявлено, но не определено переменная или функция.

Типичным объявлением переменной является

. Поскольку это только объявление, требуется одно определение. Соответствующим определением будет:

Например, следующее генерирует ошибку:

Аналогичные замечания относятся к функциям. Объявление функции без ее определения приводит к ошибке:

Будьте осторожны, чтобы выполняемая вами функция точно соответствовала той, которую вы объявили. Например, у вас могут быть несогласованные cv-квалификаторы:

Другие примеры несоответствий включают

  • Функция / переменная, объявленная в одном пространстве имен, определенное в другом.
  • Функция / переменная, объявленная как член класса, определяемая как глобальная (или наоборот).
  • Тип возвращаемого значения функции, номер и типы параметров и соглашение о вызове не совсем точно согласуются.
  • ссылка на неразрешенный внешний символ .
  • неопределённая ссылка на символ .
  • unresolved external symbol .
  • undefined reference to .
  • ошибка LNK2019 .


27.2k 10 10 золотых знаков 47 47 серебряных знаков 108 108 бронзовых знаков

Определение

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

К таким сущностям может относиться, например, функция или переменная.

Причины и решения

Возможных причин появления ошибки может быть несколько и это зависит от того, что представляет из себя собираемый проект. Всё множество ситуаций можно разбить на две большие группы:

Используются сторонние библиотеки

Не указана необходимая (статическая) библиотека для компоновщика.

Например, к проекту подключен только *.h файл с объявлениями, но отсутствует код реализации, обычно это *.lib или *.a файлы (в зависимости от используемой системы). Требуется явно подключить библиотеку к проекту.

Для Visual C++ это можно сделать добавлением следующей строки прямо в код:

Для gcc/clang требуется указать файл через ключ -l (эль)

Для Qt в .pro файле нужно использовать переменную LIBS :

Для системы сборки cmake есть target_link_libraries .

Библиотека указана, но необходимая сущность, например, класс или функция фактически не экспортируется из библиотеки. Под Windows это может возникать из-за отсуствия __declspec(dllexport) перед сущностью. Обычно это решается макросами. Данная ситуация чаще всего характерна именно для библиотек, находящихся в процессе разработки, и доступных для модификации самому разработчику, нежели для каких-то стабильных версий действительно внешних для проекта библиотек. После разрешения экспортирования библиотеку, конечно же, нужно пересобрать перед непосредственным использованием проблемной сущности.

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

В общем случае, разрядность собираемого проекта (приложения или библиотеки) должна совпадать с разрядностью используемой сторонней библиотеки. Обычно производители библиотек предоставляют возможность выбора 32 или 64 бит версию использовать. Если библиотека поставляется в исходных кодах и собирается отдельно от текущего проекта, нужно также выбрать правильную разрядность.

Библиотека указана, но она собрана для другой (не совместимой) ОС.

Например при сборке проекта в Windows осуществляется попытка использовать бинарный файл, собранный для Linux. В данном случае нужно использовать файлы, подходящие для вашей ОС.

Библиотека указана, но она собрана другим компилятором, не совместимым с используемым.

Объектные файлы, полученные путем сборки C++ кода разными компиляторами для одной и той же ОС могут быть бинарно несовместимы друг с другом. Требуется использовать совместимые (скорее всего и вовсе одинаковые) компиляторы.

Библиотека указана, и собрана тем же компилятором, что и основной проект, но используются разные версии Run-Time библиотек.

Например, для Visual C++ возможна ситуация, когда библиотека собрана с ключом /MDd , а основной проект с /MTd . Требуется задать ключи так, чтобы использовались одинаковые версии Run-Time библиотек.

Сторонние библиотеки не используются

Просто отсутствует определение функции.

Требуется добавить определение функции f :

Может быть ещё частный случай с ошибкой вида:

Такая ошибка возникает, если объявленная виртуальная функция класса, не являющаяся чистой ( =0 ), не содержит реализации.

Нужно такую реализацию добавить. Если это делается вне класса, надо не забыть указать имя проблемного класса, иначе это будет просто свободная функция, которая не устраняет указанную проблему:

Аналогичная ситуация может возникать при использовании пространств имён, когда объявлении функции находится в пространстве имён:

а при реализации указать это пространство имён забыли:

Стоит заметить, что C++ разрешает перегрузку функций (существование одноимённых функций, но с разным набором параметров), и в этом случае важно, чтобы сигнатуры функций при объявлении и определении совпадали. Например, вместо объявленной void f(int) была реализована другая:

При вызове f(42) будет ошибка:

Наличие связки шаблонного класса и дружественной функции также может приводить к ошибке. Например:

Чтобы объявить шаблонную дружественную функцию, требуется добавить указание шаблонности:

Важно, что имя шаблонного параметра для дружественной функции должно отличаться от имени параметра шаблонного класса T , т.к. иначе будет ошибка о сокрытии имени. В частном случае имя класса можно вовсе не указывать, и оставить template <class> . Но это не всегда будет правильным решением, т.к. фактически могла потребоваться дружественная специализация шаблона функции, а не сама шаблонная функция. Подробнее об использовании дружественных функций в шаблонном классе можно ознакомиться здесь.

Отсутствует определение статической переменной класса.

Нужно добавить определение (выделить память) переменной:

Неправильная реализация шаблонного кода.

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

Файл с кодом не был скомпилирован.

Например, в случае использования make-файла не было прописано правило построения файла, а в случае использования IDE типа Visual Studio *.cpp файл не добавлен в список файлов проекта.

Виртуальная функция в базовом классе не объявлена как = 0 (pure-virtual).

При использовании иерархии классов функция в базовом классе, не имеющая реализации должна быть помечена как "чистая":

Имя не имеет внешнего связывания.

Например, есть объявление функции f в модуле А и даже ее реализация в модуле B , но реализация помечена как static :

Аналогичная ситуация может возникнуть при использовании безымянного пространства имен:

я использую Visual Studio 2013. Я сделал имя решения MyProjectTest Это структура моего тестового решения:

The structure

в дереве решений Visual Studio щелкните правой кнопкой мыши на проекте "UnitTest1", затем добавьте -> существующий элемент -> выберите файл ../MyProjectTest / функция.cpp

Так как я хочу, чтобы мой проект компилировался в автономный EXE, я связал UnitTest проект с функцией.obj файл, созданный из функции.cpp и это работает. Щелкните правой кнопкой мыши на проекте 'UnitTest1' > свойства конфигурации > Компоновщик > ввод > дополнительные зависимости > добавить "..\MyProjectTest\Debug\function.obj"

оказалось, что я использовал .c файлов с .cpp-файлы. переименование. С до .cpp решил мою проблему.

другой способ, которым вы можете получить эту ошибку компоновщика (как и я), если вы экспортируете экземпляр класса из dll, но не объявили, что сам класс как импорт/экспорт.

так что, хотя в первую очередь я экспортировал только экземпляр книги класс book выше, я должен был объявить Book класс, как экспорт/импорт класса, а в противном случае вызов book.WordCount() в другой dll вызывал ошибку ссылки.

Я только что обнаружил, что LNK2019 происходит во время компиляции в Visual Studio 2015, если забыли предоставить определение для объявленной функции внутри класса.

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

для меня работает, если я добавлю эту строку ниже в .vcxproj in itemGroup cpp файл, который подключен к заголовочному файлу.

Это случилось со мной, поэтому я подумал, что могу поделиться своим решением, так просто, как это было:

Проверьте набор символов обоих проектов в Свойства Конфигурации ->общие ->Набор Символов

мой UnitTest проект использовал набор символов по умолчанию Мульти-Байт в то время как мои libs где в Unicode.
Моя функция была с помощью TCHAR в качестве параметра. В результате в моей lib мой TCHAR был преобразовано на WCHAR но это char* на моем UnitTest: символ был другим, потому что параметры были действительно не то же самое в конце концов.

в Visual Studio 2017 если вы хотите протестировать общедоступные члены, просто поместите свой реальный проект и тестовый проект в одно и то же решение и добавьте ссылку на свой реальный проект в тестовом проекте.

посмотреть модульное тестирование C++ в Visual Studio из блога MSDN для получения более подробной информации. Вы также можете проверить написать модульные тесты для C / C++ в Visual Studio а также используйте платформу модульного тестирования Microsoft для C++ в Visual Studio, причем если вам нужно протестировать непубличных членов и нужно поместить тесты в тот же проект, что и ваш реальный код.

обратите внимание, что вещи, которые вы хотите протестировать должны быть экспортированы с помощью __declspec(dllexport) . Смотрите экспорт из DLL с помощью _ _ declspec (dllexport) для более подробной информации.

Устранение ошибок LNK2019, LNK2001 и LNK1120 в Visual Studio 2017 VS2017

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


Видно, что эта ошибка в основном связана с функцией поиска. Ожидается, что файл lib поиска не включен в атрибут. Решение следующее:

Щелкните правой кнопкой мыши проект, чтобы открыть страницу свойств, страницу свойств -> компоновщик -> ввод -> дополнительные зависимости


Просто введите абсолютный путь к файлу lib в дополнительных зависимостях и добавьте его. Обратите внимание, что здесь нет кнопки добавления. Вы можете ввести его только вручную. Просто найдите существующий, поместите курсор в конец и нажмите Enter, чтобы вставить необходимую библиотеку. Абсолютный путь к файлу в порядке.

Перекомпилируйте и сгенерируйте, проблема решена.


Обратите внимание на добавление файлов lib! ! !


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

Интеллектуальная рекомендация


[Makefile от более мелких к более глубоким полная запись обучения 4] Переменные и различные методы присвоения

Давайте сегодня узнаем о различных методах присваивания переменных в Makefile! Смысл тяжелой работы, чтобы бедность больше не ограничивать свое воображение! Добавьте QQ, чтобы вместе учиться и обменив.

[Luogu P3147] [BZOJ 4576] [USACO16OPEN]262144

Портал Луогу БЗОЙ Портал Описание заголовка Bessie likes downloading games to play on her cell phone, even though she doesfind the small touch screen rather cumbersome to use with her large hooves. Sh.

Читайте также: