Приложение не работает с DLL-библиотеками VS 2008 SP1, предыдущая версия работает с версиями RTM

Компилятор будет генерировать код для каждого экземпляра шаблона при использовании шаблона во время этапа компиляции. В процессе компиляции и компоновки файлы .cpp преобразуются в чистый объектный или машинный код, который в них содержит ссылки или неопределенные символы, поскольку файлы .h, которые включены в ваш main.cpp, не имеют реализации YET. Они готовы быть связаны с другим объектным файлом, который определяет реализацию для вашего шаблона, и, следовательно, у вас есть полный исполняемый файл a.out. Однако, поскольку шаблоны необходимо обработать на этапе компиляции, чтобы сгенерировать код для каждого экземпляра шаблона, который вы делаете в своей основной программе, ссылка не поможет, поскольку компиляция main.cpp в main.o, а затем компиляция вашего шаблона .cpp в template.o, а затем ссылка не будет достигать цели шаблонов, потому что я связываю различные экземпляры шаблонов с одной и той же реализацией шаблона! И шаблоны должны делать обратное, т. Е. Иметь одну реализацию, но допускать много доступных экземпляров посредством использования одного класса.

Значение typename T get заменяется во время этапа компиляции, а не на этапе связывания, поэтому, если я попытаюсь для компиляции шаблона без замены T в качестве конкретного типа значения, чтобы он не работал, потому что это определение шаблонов - это процесс времени компиляции, а мета-программирование btw - все об использовании этого определения.

37
задан crashmstr 2 November 2008 в 02:00
поделиться

5 ответов

Я боролся против этой проблемы сам на прошлой неделе и считаю меня своего рода экспертом теперь;)

я на 99% уверен, что не весь dlls и статические библиотеки были перекомпилированы с версией SP1. Необходимо поместить

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

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

существует больше флагов, которые определяют что версии связать с; это документируется на http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx . Как альтернатива строкам выше, можно также поместить

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

, который свяжет с последней версией всего VC, освобождает (CRT, MFC, ATL, OpenMP).

Затем проверьте то, что говорит встроенная декларация. Загрузите Редактора Ресурса XM: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm . Откройте каждый dll и exe в Вашем решении. Посмотрите в соответствии с 'Декларацией Темы XP'. Проверьте, что атрибут 'версии' на правой стороне '9.0.30729.1'. Если это '9.0.21022', некоторая статическая библиотека вытягивает в декларации для старой версии.

то, Что я нашел, - то, что во многих случаях, оба версии были включены в декларацию. Это означает, что некоторые библиотеки используют sp1 версию, и другие не делают.

отличный способ А отладить, каким библиотекам не установили директивы препроцессору: временно измените свои заголовки платформы так, чтобы компиляция остановилась, когда она пытается встроить старую декларацию. Откройте C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h. Ищите эти '21022' строка. В этом определяют, помещают что-то недопустимое (изменение 'определяют' к 'blehbleh' или так). Этот путь при компиляции проекта, где _BIND_TO_CURRENT_CRT_VERSION флаг препроцессора не установлен, компиляция, остановится, и Вы будете знать, что должны добавить их или удостоверились, что это применяется везде.

Также удостоверяются, что использовали Зависимость Walker так, чтобы Вы знали, какие dlls втягиваются. Является самым легким установить новую копию Windows XP без обновлений (только SP2) на виртуальной машине. Таким образом, Вы знаете наверняка, что нет ничего в папке SxS, которая используется вместо бок о бок dlls, что Вы предоставили.

40
ответ дан Roel 2 November 2008 в 02:00
поделиться

Я просто помнил другой прием, который я раньше узнавал, какие статические библиотеки плохо вели себя: 'grep' через статические библиотеки для строки '21022'. ОДНАКО не используйте 'нормальные' grep инструменты как wingrep, потому что они не покажут Вам эти строки (они думают, что это - двоичный файл, и ищите сырые данные, non-unicode строка). Используйте 'строковую' утилиту от набора ресурса (теперь в сайте Russinovich, я думаю). Тот будет grep через двоичные файлы хорошо. Таким образом, Вы позволяете, это 'представляет в виде строки', проходят Ваше целое исходное дерево, и Вы будете видеть двоичные файлы (dlls и статические библиотеки), которые содержат ссылки на неправильную декларацию (или на декларацию с неверной версией в нем).

4
ответ дан Roel 2 November 2008 в 02:00
поделиться

Для вашего третьего варианта вы, вероятно, можете найти библиотеки DLL и манифесты для версии 9.0.21022 в каталоге C: \ WINDOWS \ WinSxS на вашем компьютере разработчика. Если вы можете, вы можете настроить свой собственный каталог для перенаправления и установить эти файлы с вашим приложением.

В качестве альтернативы вы можете использовать 9.0.30729.1, поставляемые с Visual Studio, и подделать манифест, который вы устанавливаете с вашим приложением, чтобы сообщить, что он предоставляет библиотеки DLL 9.0.21022, а не 9.0.30729.1. Компоновщик среды выполнения не Кажется, я не против. См. Этот блог , который был чрезвычайно полезен для решения этих проблем, для получения дополнительной информации.

Оба обходных пути устранили проблемы, с которыми я столкнулся при развертывании библиотек DLL в виде частных сборок с VS2008 Express.

Ответ Роэла - это способ выбрать ваш первый вариант («исправить это правильно»), но если вы зависите от библиотеки, которая зависит от 9.0.21022 (и, следовательно, в вашем манифесте перечислены обе версии), то третий вариант может быть единственным способом перейдите, если вы не хотите запускать vcredist_x86.exe.

2
ответ дан 27 November 2019 в 04:43
поделиться

Еще один удобный инструмент для просмотра манифестов exe и dll - это Manifest View , который, как ни странно, не будет работать при чистой установке XP, потому что это зависит от 9.0.21022.

4
ответ дан 27 November 2019 в 04:43
поделиться

Чтобы понять проблему, я думаю, важно понимать, что есть четыре задействованных номера версии :

  • (A) Версия файлов заголовков VC, в которые скомпилирован .exe.
  • (B) Версия файла манифеста, встроенного в раздел ресурсов этого .exe. По умолчанию этот файл манифеста автоматически создается Visual Studio.
  • (C) Версия VC .DLL (часть параллельной сборки), которую вы копируете в тот же каталог, что и .exe.
  • (D) Версия файлов манифеста VC (часть параллельной сборки), которую вы копируете в тот же каталог, что и .exe.

В работе находятся две версии библиотеки DLL VC 2008:

  • v1: 9.0.21022.8
  • v2: 9.0.30729.4148

Для ясности я буду использовать обозначение v1 / v2. В следующей таблице показан ряд возможных ситуаций:

Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1         | v2       | v1                    | v1          | v1         
2         | v2       | v1                    | v2          | v2          
3         | v2       | v1                    | v2          | v1
4         | v2       | v2                    | v2          | v2

Результатами этих ситуаций при запуске .exe в чистой установке Vista SP1 являются:

  • Ситуация 1: отображается всплывающее окно с сообщением: «Точка входа в процедуру XYZXYZ не удалось найти в библиотеке динамической компоновки ".

  • Ситуация 2: кажется, что при запуске .exe ничего не происходит, но в «Журнале просмотра событий / журнале приложений» Windows регистрируется следующее событие:

    Сбой создания контекста активации для «C: \ Path \ file.exe. ".Ошибка в манифесте или файле политики" C: \ Path \ Microsoft.VC90.CRT.MANIFEST "в строке 4. Идентификатор компонента, обнаруженный в манифесте, не соответствует идентификатору запрошенного компонента. Ссылка: Microsoft.VC90.CRT, processorArchitecture = "x86", publicKeyToken = "1fc8b3b9a1e18e3b", type = "win32", version = "9.0.21022.8".Определение Microsoft

  • Ситуация 3: вроде все работает нормально. Это решение remicles2 .

  • Ситуация 4: это , как это должно быть сделано . К сожалению, как указывает Рул,это может быть довольно сложно реализовать.

Теперь моя ситуация (и я думаю, что она такая же, как crashmstr ) - номер 1. Проблема в том, что Visual Studio по той или иной причине генерирует клиентский код (A) для v2, но для по той или иной причине создается файл манифеста v1 (B). Понятия не имею, где можно настроить версию (A).

Обратите внимание , что все это объяснение все еще относится к частным собраниям .

Обновление : наконец-то я начинаю понимать, что происходит. Очевидно, Visual Studio по умолчанию генерирует клиентский код (A) для v2 , в отличие от того, что я читал в некоторых блогах Microsoft. Флаг _BIND_TO_CURRENT_VCLIBS_VERSION выбирает только версию в сгенерированном файле манифеста (B), но эта версия будет проигнорирована при запуске приложения.

Заключение

.exe, скомпилированный Visual Studio 2008, по умолчанию ссылается на новейшие версии библиотек DLL VC90. Вы можете использовать флаг _BIND_TO_CURRENT_VCLIBS_VERSION , чтобы контролировать, какая версия библиотек VC90 будет сгенерирована в файле манифеста. Это действительно позволяет избежать ситуации 2, когда вы получаете сообщение об ошибке «манифест не соответствует идентификатору запрошенного компонента». Это также объясняет, почему ситуация 3 работает нормально, поскольку даже без флага _BIND_TO_CURRENT_VCLIBS_VERSION приложение связано с новейшими версиями библиотек DLL VC.

Ситуация еще более странная с общедоступными параллельными сборками, в которых запускался vcredist, помещающий библиотеки DLL VC 9.0 в каталог Windows SxS. Даже если.В файле манифеста exe указано, что следует использовать старые версии DLL (это тот случай, когда флаг _BIND_TO_CURRENT_VCLIBS_VERSION не установлен), Windows игнорирует этот номер версии по умолчанию! Вместо этого Windows будет использовать более новую версию, если она присутствует в системе, за исключением , когда используется «файл конфигурации приложения» .

Я единственный, кто думает, что это сбивает с толку?

Итак вкратце :

  • Для частных сборок используйте флаг _BIND_TO_CURRENT_VCLIBS_VERSION в проекте .exe и все ] зависимые проекты .lib.
  • Для общедоступных сборок это не требуется, поскольку Windows автоматически выберет правильную версию .DLL из каталога SxS.
14
ответ дан 27 November 2019 в 04:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: