2009-10-14 4 views
1

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

Я знаю, что не стоит смешивать статически связанные и динамически связанные C и C++ среды выполнения, поставляемые Microsoft. Наше приложение на работе уже смешает их, к сожалению, и мы пытаемся это исправить. По разным причинам (среди которых незнакомость с MSI, тот факт, что мы используем NSIS, который, возможно, не поддерживает МСМ, нехватка времени и ресурсов), мы решили связать ЭЛТ статически, а не динамически. Я знаю причины, почему это не очень хорошая идея, но пока это был наш выбор.


Наш код в основном стандартный C++, дополненный множеством других библиотек с открытым исходным кодом.

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

В выпуске мы строим все наш код с/MT. Для некоторых библиотек с открытым исходным кодом мы использовали предварительно скомпилированные двоичные файлы, а некоторые из них были скомпилированы с использованием/MD, что заставило нас смешивать время выполнения. Поэтому мы перекомпилировали те, у кого есть/MT, и сделали их результатом статических библиотек, а не dll. Это преобразование не выполняется для каждой библиотеки, поэтому мы по-прежнему связываемся с некоторыми DLL, которые используют/MD.


В результате в настоящее время является то, что в depends.exe всех наших вещей за исключением одного исполняемого не непосредственно зависит от MSVCR80.DLL или MSVCP80.DLL. К напрямую не зависит Я имею в виду, что msvcr80.dll не является дочерним по отношению к корню дерева, показанному параметром depend.exe. Иногда мы находим файл msvcr80.dll в одной библиотечной библиотеке, но на некоторых уровнях глубже.

Как узнать, почему msvcr80.dll на первом уровне для этого надоедливого исполняемого файла? Что делает эту исполняемую ссылку непосредственно в msvcr80.dll?

Одна из причин может быть связана с тем, что мы связываем статически с библиотекой A, в которой используются ссылки/MD, поэтому она динамически связывается с CRT. Таким образом, код в библиотеке A заканчивается в нашем исполняемом файле, поэтому наши исполняемые ссылки с msvcr80.dll. Но как мне узнать, какая из библиотек это делает?


То, что я пытался до сих пор:

  • нагрузки статически связанные .lib файлы в depends.exe -> не работает, так как depends.exe ожидает исполняемый файл или DLL не статическая библиотека
  • использовать dumpbin.exe/DIRECTIVES на статически связанных .lib-файлах -> ни один из них не показал msvcrt80.dll (в то время как в Debug, где мы пытаемся использовать/MDd для всего, они отображали msvcrt80d.dll, что заставляет меня думать, что метод хорош, и он доказывает, что все статически связанные библиотеки с открытым исходным кодом скомпилированы с помощью/MT)
  • использовать флаг/VERBOSE: LIB linker -> он показал, что он действительно загружается в msvcrt.lib, который является библиотекой импорта для msvcr80.dll, так что у нас проблемы, но он не сказал, почему это делается
  • используйте флаг link/VERBOSE + в Visual Studio: дополнительные зависимости libcmt.lib + Игнорировать все библиотеки по умолчанию YES + Игнорировать определенную библиотеку: msvcrt.lib в отчаянной попытке сделать msvcrt.lib уйти или посмотреть, кто его тянет. Результат озадачен меня:
 
    Searching C:\Program Files\Microsoft Visual Studio 8\VC\lib\msvcrt.lib: 
     Found "public: virtual void * __thiscall type_info::`vector deleting destructor'(unsigned int)" ([email protected]@[email protected]) 
     Referenced in libcmt.lib(typinfo.obj) 
     Loaded msvcrt.lib(ti_inst.obj) 
      msvcrt.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" ([email protected]@[email protected]@@Z) already defined in libcmt.lib(typinfo.obj) 
      msvcrt.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" ([email protected]@[email protected]@@Z) already defined in libcmt.lib(typinfo.obj) 
     Found "void __stdcall `eh vector destructor iterator'(void *,unsigned int,int,void (__thiscall*)(void *))" ([email protected]@[email protected]) 
     Referenced in msvcrt.lib(ti_inst.obj) 
     Loaded msvcrt.lib(ehvecdtr.obj) 

Насколько я понимаю, typinfo.obj в библиотеку libcmt.lib ссылается на символ, ищет его в MSVCRT.lib и после того, как он находит в ti_inst.obj он выдает ошибку, что он определяется дважды. Но это не имеет смысла. Если libcmt.lib уже имеет символ, почему он в конечном итоге ищет его в msvcrt.lib и, следовательно, приносит msvcr80.dll в мой исполняемый файл? И в более общем плане, почему статическая библиотека будет искать символы в динамической библиотеке импорта? Почему линкер даже смотрит на msvcrt.lib, если у меня есть его в библиотеке Ignore?

Благодарим за ваше терпение :-).

ответ

3

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

msvcrt.lib был явно упомянут нами в поле «Дополнительные зависимости»: (так что, конечно, это сделало зависимость dll a. И из-за всех библиотек с открытым исходным кодом в этом поле есть много текста, и, честно говоря, мы даже не думали внимательно смотреть на эту коробку, так как мы не думали, что в наших проектах может быть такая грубая ошибка.

1

Откройте ваш исполняемый файл с помощью файла depend.exe и запустите встроенный профилировщик. Я считаю, что это запишет, почему загружаются все ваши DLL и откуда они загружаются. См. Раздел «Функции вызова функции« Загрузка LoadLibrary ».

+0

Спасибо за предложение. Это сработало бы, если бы мое приложение будет вызывать LoadLibrary на msvcrt80.dll, поэтому, если эта DLL будет задерживаться, но я напрямую свяжусь с ней, поэтому я вижу только: Загруженный «MSVCR80.DLL» по адресу 0x78130000 по потоку 1. Успешно подключенный модуль. Проблема оказалось, было вызвано глупой ошибкой, см. мой ответ. –

Смежные вопросы