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

StackOverflow https://stackoverflow.com/questions/1569222

Вопрос

Извините за длинный пост, который следует далее.

Я знаю, что не стоит смешивать статически связанные и динамически связанные среды выполнения C и C ++, предоставляемые Microsoft.К сожалению, наше приложение на работе уже смешивает их, и мы пытаемся это исправить.По разным причинам (среди которых незнание MSI, тот факт, что мы используем NSI, которые, возможно, плохо поддерживают MSMS, нехватка времени и ресурсов) мы решили связать CRT статически, а не динамически.Я знаю причины, по которым это не очень хорошая идея, но на данный момент это был наш выбор.


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

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

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


Результатом сейчас является то, что в depends.exe все наши материалы кроме одного исполняемого файла не делает непосредственно зависеть от msvcr80.dll или msvcp80.dll.Автор: напрямую не зависит Я имею в виду, что msvcr80.dll не является дочерним элементом корня дерева, показанного depends.exe.Иногда мы обнаруживаем msvcr80.dll подключено одной из библиотек DLL, но это на несколько уровней глубже в дереве.

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

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


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

  • загрузите статически связанные файлы .lib в depends.exe -> не работает, поскольку depends.exe ожидает исполняемый файл или dll, а не статическую библиотеку
  • используйте dumpbin.exe ДИРЕКТИВЫ / для статически связанных файлов .lib -> ни один из них не отображался msvcrt80.dll (во время отладки, где мы пытаемся использовать / MDd для всего, они отображались msvcrt80d.dll что заставляет меня думать, что метод хорош, и это доказывает, что все статически связанные библиотеки с открытым исходным кодом корректно скомпилированы с помощью / MT)
  • используйте флаг компоновщика /VERBOSE:LIB -> это показало, что он действительно загружает msvcrt.lib, который является библиотекой импорта для msvcr80.dll итак, мы в беде, но в нем не было сказано, почему он это делает
  • используйте флаг компоновщика /VERBOSE + в Visual Studio:Дополнительные зависимости libcmt.lib + Игнорировать все библиотеки по умолчанию ДА + Игнорировать конкретную библиотеку: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)" (??_Etype_info@@UAEPAXI@Z)  
        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 &)" (??0type_info@@AAE@ABV0@@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 &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)  
      Found "void __stdcall `eh vector destructor iterator'(void *,unsigned int,int,void (__thiscall*)(void *))" (??_M@YGXPAXIHP6EX0@Z@Z)  
        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 specific?

Спасибо за ваше терпение :-).

Это было полезно?

Решение

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

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

Другие советы

Откройте свой исполняемый файл с помощью depends.exe и запустите профилировщик, встроенный в depends.Я полагаю, что это будет регистрировать, почему загружены все ваши библиотеки dll и откуда они загружены.Смотрите опцию "Регистрировать вызовы функций LoadLibrary".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top