С++ компоновщик неразрешенных внешних символов

Я создаю приложение для некоторых устаревших сторонних библиотек и имею проблемы на этапе связывания. Я пытаюсь скомпилировать с помощью Visual Studio 9. Моя команда компиляции:

cl -DNT40 -DPOMDLL -DCRTAPI1=_cdecl
-DCRTAPI2=cdecl -D_WIN32 -DWIN32 -DWIN32_LEAN_AND_MEAN -DWNT -DBYPASS_FLEX -D_INTEL=1 -DIPLIB=none -I. -I"D:\src\include" -I"C:\Program Files\Microsoft Visual Studio
9.0\VC\include" -c -nologo -EHsc -W1 -Ox -Oy- -MD mymain.c

Код компилируется чисто. Команда ссылки:

link -debug -nologo -machine:IX86
-verbose:lib -subsystem:console mymain.obj wsock32.lib advapi32.lib
msvcrt.lib oldnames.lib kernel32.lib
winmm.lib [snip large list of
dependencies] D:\src\lib\app_main.obj
-out:mymain.exe

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

app_main.obj : error LNK2019:
unresolved external symbol
"_\_declspec(dllimport) public: void
__thiscall std::locale::facet::_Register(void)"
(__imp_?_Register@facet@locale@std@@QAEXXZ)
referenced in function "class
std::ctype<char> const & __cdecl
std::use_facet<class std::ctype<char>
(class std::locale const &)" (??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z)

app_main.obj : error LNK2019:
unresolved external symbol
"__declspec(dllimport)  public: static
unsigned int __cdecl
std::ctype<char>::_Getcat(class
std::locale::facet const * *)"
(__imp_?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@@Z)
referenced in function "class
std::ctype<char> const & __cdecl
std::use_facet<class std::ctype<char>
(class std::locale const &)" (??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z)

app_main.obj : error LNK2019:
unresolved external symbol
"__declspec(dllimport)  public: static
unsigned int __cdecl
std::ctype<unsigned
short>::_Getcat(class
std::locale::facet const * *)"
(__imp_?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@@Z)
referenced in function "class
std::ctype<unsigned short> const &
__cdecl std::use_facet<class std::ctype<unsigned short> >(class
std::locale const &)"
(??$use_facet@V?$ctype@G@std@@@std@@YAABV?$ctype@G@0@ABVlocale@0@@Z)

mymain.exe : fatal error LNK1120: 3
unresolved externals

Обратите внимание, что эти ошибки исходят из устаревшего кода, а не моего кода — app_main.obj является частью устаревшего кода, а mymain.c — моим источником. Я немного поискал, и то, что я прочитал, говорит о том, что этот тип ошибки вызван несоответствием переключателя -MD между моим кодом и библиотекой, на которую я ссылаюсь. Поскольку я имею дело с устаревшим кодом, решение должно исходить из моей среды. Прошло много времени с тех пор, как я работал с C++, и еще больше с тех пор, как я использовал Visual Studio, поэтому я надеюсь, что это просто невежество с моей стороны. Любые идеи о том, как решить эти проблемы?


c++
person Matt McMinn    schedule 22.08.2008    source источник


Ответы (4)


Это стандартные библиотечные ссылки. Убедитесь, что все библиотеки (включая стандартную библиотеку) используют одну и ту же связь. Например. вы не можете ссылаться статически, динамически связывая стандартную библиотеку. То же самое касается используемой модели потоков. Обратите особое внимание на то, чтобы вы и сторонняя библиотека использовали одни и те же параметры связывания.

Это может быть настоящей головной болью *ss.

person Konrad Rudolph    schedule 22.08.2008

Проверьте это на MSDN :

  • /MD Заставляет ваше приложение использовать версию библиотеки времени выполнения, специфичную для многопоточности и DLL.
  • /MT Заставляет ваше приложение использовать многопоточную статическую версию библиотеки времени выполнения.

Примечание: "... чтобы компоновщик использовал LIBCMT.lib для разрешения внешних символов"

Поэтому вам понадобится другой набор библиотек.

Как я начал выяснять, какие библиотеки связать:

  1. Найдите конфигурацию, которая делает ссылку, и добавьте параметр /verbose.
  2. Направьте вывод в текстовый файл.
  3. Попробуйте конфигурацию, которая нет связи.
  4. Найдите в подробном выводе шага 2 неразрешенные символы ("_declspec(dllimport) public: void thiscall std::locale::facet::Register(void)" в вашем случае) и найдите используемые библиотеки.
  5. Добавьте эти библиотеки в список библиотек, на которые вы ссылаетесь.

Старая школа, но она работала для меня.

Ян

person jan    schedule 25.08.2008

Если вы все еще хотите, чтобы проект компилировался с использованием VS2008 (или в будущем), я могу предложить использовать двоичный редактор для просмотра рассматриваемого объектного файла mainapp.obj.

Вот пример из моего небольшого проекта.

zdbException.obj содержит следующую выдержку

DEFAULTLIB:"libc
pmtd" /DEFAULTLI
B:"uuid.lib" /DE
FAULTLIB:"uuid.l
ib" /include:?id
@?$num_put@DV?$o
streambuf_iterat
or@DU?$char_trai
ts@D@std@@@std@@
@std@@2V0locale@
2@A /include:?id
@?$numpunct@D@st
d@@2V0locale@2@A
 /DEFAULTLIB:"LI
BCMTD" /DEFAULTL
IB:"OLDNAMES" /E
DITANDCONTINUE 

Обратите внимание на запись /DEFAULTLIB:"LIBCMTD". Это указывает на то, что объектный файл был скомпилирован с помощью статической многопоточной отладки времени выполнения c.

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

person Henk    schedule 04.09.2008

После попытки компилировать этот материал под VS 2008, я попробовал более ранние версии VS - 2005 работал с предупреждениями, а 2003 просто работал. Я дважды проверил связи и не смог найти никаких проблем, так что либо я просто не смог их найти, либо проблема была не в этом.

Итак, повторюсь, переход на VS 2003 исправил это.

person Matt McMinn    schedule 25.08.2008