Ошибка LNK2001 при компиляции приложений, ссылающихся на STLport-5.1.4 с VC ++ 2008 - PullRequest
2 голосов
/ 04 ноября 2008

заранее прошу прощения за длинный пост ...

Раньше я имел возможность создавать наши решения VC ++ (мы на VS 2008), когда мы перечисляли каталоги включения и библиотеки STLPort в меню VS Menu> Инструменты> Параметры> Каталоги VC ++> Каталоги для файлов включений и библиотек. Однако мы хотели перейти к процессу сборки, который полностью основан на файлах .vcproj и .sln. Они могут быть проверены в управлении исходным кодом в отличие от VS Options, которые должны быть настроены на каждом компьютере разработки отдельно. Мы осуществили переход для большинства библиотек, добавив каталоги «Включить» на страницах свойств каждого проекта> Свойства конфигурации> C / C ++> Общие> Дополнительные каталоги включения и «Библиотеки» в «Линкер»> «Общие»> «Дополнительные каталоги библиотеки».

К сожалению, этот подход не работает для STLPort. Мы получаем ошибки LNK2019 и LNK2001 во время связывания:

Error   1   error LNK2019: unresolved external symbol "public: virtual bool __thiscall MyClass::myFunction(class stlp_std::basic_istream<char,class stlp_std::char_traits<char> > &,class MyOtherClass &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > &)const " (?myFunction@MyClass@@UBE_NAAV?$basic_istream@DV?$char_traits@D@stlp_std@@@stlp_std@@AAVSbprobScenarioData@@AAV?$basic_string@DV?$char_traits@D@stlp_std@@V?$allocator@D@2@@3@@Z) referenced in function _main MyLibrary.obj   

Error   5   error LNK2001: unresolved external symbol "public: static void __cdecl MyClass::myFunction(class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,long,enum MyClass::MessageType,int,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &)" (?myFunction@MyClass@@SAXABV?$basic_string@DV?$char_traits@D@stlp_std@@V?$allocator@D@2@@stlp_std@@000JW4MessageType@1@H0@Z)  MyLibrary.lib   

Это происходит при связывании и выполнении проекта с зависимостями, которые являются проектами библиотеки. Любопытно, что этого не происходит при связывании самих библиотечных проектов. Есть идеи?

Ответы [ 6 ]

5 голосов
/ 26 марта 2009

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

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

Введите undname.exe:


undname.exe
  • - простая программа командной строки, которая находится в вашем каталоге VS bin.
  • принимает украшенное имя в качестве первого аргумента.
  • выводит читабельный формат символа.

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

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

Введите dumpbin.exe:


dumpbin.exe <имя библиотеки>
  • - это простая программа командной строки, которая находится в вашем каталоге VS bin.
  • принимает набор ключей и библиотеку для их применения.
  • выводит информацию из библиотеки

Переключатель, который вас заинтересует для вашего вопроса: / linkermember . Есть много других переключателей, которые могут дать вам очень интересную информацию, но этот перечислит все символы в библиотеке.

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

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

Предполагается, что ваше сообщение об ошибке было таким:

Error   1       error LNK2019: unresolved external symbol "public: unsigned char __cdecl TiXmlComment::Accept(bool,class TiXmlVisitor *) " (?Accept@TiXmlComment@@ZBE_NPAVTiXmlVisitor@@@Z) referenced in function _main     MyLibrary.obj 

Определив, что это функция в TinyXML, я могу начать искать несоответствующий символ. Я начну со сброса членов библиотеки. (Заметьте, что переключатель в единственном числе, я всегда получаю его, когда набираю его по памяти!)


>dumpbin /linkermember tinyxml.lib
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file tinyxml.lib

File Type: LIBRARY

Archive member name at 8: /
4992E7BC time/date Wed Feb 11 08:59:08 2009
         uid
         gid
       0 mode
    B402 size
correct header end

    859 public symbols

    16292 ??$_Allocate@D@std@@YAPADIPAD@Z
    16292 ??$_Char_traits_cat@U?$char_traits@D@std@@@std@@YA?AU_Secure_char_traits_tag@0@XZ
    16292 ??$copy_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDI@Z
    16292 ??$copy_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDIU_Secure_char_traits_tag@1@@Z
    16292 ??$move_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDI@Z
    16292 ??$move_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDIU_Secure_char_traits_tag@1@@Z
    16292 ??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z
    16292 ??0?$_String_val@DV?$allocator@D@std@@@std@@IAE@V?$allocator@D@1@@Z
    16292 ??0?$_String_val@DV?$allocator@D@std@@@std@@QAE@ABV01@@Z

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


>dumpbin /linkermember tinyxml.lib | grep Accept
    529AE ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlDeclaration@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlDocument@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlElement@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlText@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlUnknown@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlDeclaration@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlDocument@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlElement@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlText@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlUnknown@@UBE_NPAVTiXmlVisitor@@@Z

Это намного легче читать. Глядя на нашу ошибку, мы ищем функцию принятия TiXmlComment. Мы могли бы получить дополнительный вывод для этого имени, если бы у нас было много совпадений (например, просмотр функции размера в stl!), Но в этом случае мы можем выбрать его из списка. Здесь мы обращаемся к имени:


>undname ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z"
is :- "public: virtual bool __thiscall TiXmlComment::Accept(class TiXmlVisitor *)const "

Итак, в этом примере наше приложение ищет функцию, которая возвращает unsigned char , но в библиотеке есть функция, возвращающая bool .

Это надуманный пример, но он иллюстрирует методику, используемую для отслеживания вашей проблемы. Возможно, вы ищете тип typedef, который устанавливается по-разному в зависимости от ваших параметров.

Проблема, с которой я столкнулся, была с time_t . В некоторых библиотеках, которые я использовал, time_t использовал 32-битный тип как часть своего внутреннего представления. Эта библиотека была сгенерирована с более старым компилятором, где это было по умолчанию. В VS 2005 time_t использует 64-битный тип по умолчанию. Мне пришлось добавить определение препроцессора _USE_32BIT_TIME_T , чтобы заставить его скомпилировать. Я выследил эту проблему именно так, как я описал.

Надеюсь, это поможет кому-то решить эту проблему!

3 голосов
/ 30 декабря 2008

Раймонд Чен недавно говорил об этом на The Old New Thing - одна из причин этих проблем состоит в том, что библиотека была скомпилирована с одним набором переключателей, но ваше приложение использует другой набор. Что вам нужно сделать, это:

Получите точный символ, который ищет компоновщик. Это будет ужасное искалеченное имя. Используйте шестнадцатеричный редактор (IIRC, Visual Studio сделает это), чтобы посмотреть .lib-файл, на который вы ссылаетесь. Найдите символ, который почти то, что ищет компоновщик, но не совсем. Учитывая различия в символах, попытайтесь выяснить, какие ключи командной строки помогут. Удачи - для людей, которые не привыкли к такой проблеме, решение может занять несколько дней, чтобы выяснить (!)

1 голос
/ 21 ноября 2008

Необходимо настроить порт STL для использования собственной реализации IOStreams.

Также есть ли какая-то конкретная причина, по которой вы используете STLPort? Рекомендуется реализация STL по умолчанию, если только вы не пытаетесь создать кроссплатформенное приложение - даже в большинстве случаев оно действительно не требуется.

1 голос
/ 16 ноября 2008

Эти ошибки связи указывают на то, что определенные классы в вашем приложении либо не были скомпилированы с использованием STLPort, либо были исключены из сборки. Они не предполагают, что вы не ссылаетесь на STLport.

Мои предположения были бы таковы:

  • Настройки сборки для MyClass каким-то образом перезаписывают настройки всего проекта для пути включения, и, таким образом, MyClass создается с использованием стандартной реализации C ++ STL, а не STLport. Это должно быть легко проверить - запустите dumpbin для объектного файла и проверьте, что функции в нем ссылаются на стандартную библиотеку в пространстве имен stlp_ * или нет. Если нет, вполне вероятно, что компилятор не выбирает правильный путь включения. Я бы также взглянул на командную строку, с которой IDE вызывает компилятор. Их также можно просмотреть через свойства конфигурации C / C ++.
  • Как уже упоминалось в других постерах, существует вероятность того, что MyClass не создается, но это должно быть очень легко проверить.
0 голосов
/ 06 ноября 2008

Добавить имя библиотеки в список дополнительных библиотек для ссылки. Извините, я не нахожусь перед последней версией VS, чтобы точно знать, куда она идет.

0 голосов
/ 04 ноября 2008

Это ошибка ссылки. Это не имеет отношения к вашим путям включения.

Вы либо забыли добавить MyClass.cpp в свой проект, либо забыли определить эти две функции.

Причина, по которой ошибка не возникает при «связывании» библиотечных проектов, заключается в том, что библиотечные проекты не связаны. Это просто набор объектов OBJ, которые объединяются программой LIB в файл библиотеки.

...