Какие проблемы с переносом происходят с VC8 (VS2005) на VC9 (VS2008)? - PullRequest
3 голосов
/ 31 октября 2008

Я унаследовал очень большой и сложный проект (фактически, «решение», состоящее из 119 «проектов», большинство из которых являются DLL), который был построен и протестирован в VC8 (VS2005), и у меня есть задача портирования это к VC9 (VS2008).

Процесс портирования, который я использовал:

  1. Скопируйте файл VC8 .sln и переименуйте его в файл VC9 .sln.
  2. Скопируйте все файлы проекта VC8 и переименовать их в файлы проекта VC9.
  3. Редактировать все файлы проекта VC9, с / VC8 / VC9.
  4. Редактировать VC9 .sln, s / vc8 / vc9 /
  5. Загрузите VC9 .sln с VS2008, и пусть IDE конвертируется все файлы проекта.
  6. Fix ошибки компилятора и компоновщика, пока я получил хорошую сборку.

Пока что на последнем шаге я столкнулся со следующими проблемами.

1) Изменение способа вычисления оформленных имен, вызывающее усечение имен.

Это больше, чем просто предупреждение (http://msdn.microsoft.com/en-us/library/074af4b6.aspx). Библиотеки, созданные с этим предупреждением, не будут связываться с другими модулями. Применение решения, указанного в MSDN, было нетривиальным, но выполнимым решением. Я решил эту проблему отдельно в Как увеличить допустимую длину декорированного имени в VC9 (MSVC 2008)?

2) Изменение, которое не позволяет присвоить ноль итератору. Это в соответствии со спецификацией, и было довольно легко найти и исправить эти ранее допустимые ошибки кодирования. Вместо присвоения нулю итератору используйте значение end ().

3) область видимости для цикла теперь соответствует стандарту ANSI. Еще одна легко решаемая проблема.

4) Для предварительно скомпилированных заголовков требуется больше места. В некоторых случаях требуется гораздо больше места. В итоге я использовал / Zm999, чтобы обеспечить максимальное пространство для PCH. Если использование памяти PCH снова увеличится, я предполагаю, что мне придется полностью отказаться от PCH и просто выдержать увеличение, которое уже занимает очень много времени.

5) Изменение требований к копорам и стандартным. Похоже, что в шаблонных классах при определенных условиях, которые я до сих пор не выяснил, компилятор больше не генерирует ctor по умолчанию или dtor по умолчанию. Я подозреваю, что это ошибка в VC9, но может быть что-то еще, что я делаю неправильно. Если это так, я бы хотел знать, что это такое.

6) GUID в файлах sln и vcproj не были изменены. Кажется, это никак не влияет на сборку, которую я могу обнаружить, но, тем не менее, вызывает беспокойство.

Обратите внимание, что, несмотря на все эти проблемы, проект был собран, запущен и прошел всестороннее тестирование качества в рамках VC8. Я также перенес все изменения в проекты VC8, где они по-прежнему создаются и работают так же счастливо, как и раньше (с использованием VS2005 / VC8). Итак, все мои изменения, необходимые для сборки VC9, по крайней мере кажутся обратно совместимыми, хотя регрессионное тестирование все еще продолжается.

Теперь для действительно сложной проблемы: я столкнулся с разницей в последовательности запуска между проектами VC8 и VC9. В программе используется распределитель небольших объектов, созданный по образцу Локи, в книге Андрея Александреску Modern C ++ Design . Этот распределитель инициализируется с использованием глобальной переменной, определенной в главном программном модуле.

В VC8 эта глобальная переменная создается в самом начале запуска программы из кода в модуле crtexe.c. Под VC9 первый модуль, который выполняется, является crtdll.c, который указывает, что последовательность запуска была изменена. Библиотеки DLL, которые запускаются, по-видимому, сбивают с толку распределитель малых объектов, выделяя и освобождая память до того, как глобальный объект может инициализировать статистику, что приводит к некоторой ложной диагностике. Работа программы, по-видимому, существенно не затронута, но специалисты по обеспечению качества не позволят ложной диагностике пройти их.

Есть ли какой-нибудь способ форсировать создание глобального объекта перед загрузкой DLL?

С какими еще проблемами портирования я могу столкнуться?

Ответы [ 5 ]

1 голос
/ 04 февраля 2009

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

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

Проблема, конечно, в том, что я не могу представить себе одноэлементную реализацию, которая бы избежала описываемой вами проблемы. Может быть, это обсуждение будет полезно: http://www.oneunified.net/blog/Personal/SoftwareDevelopment/CPP/Singleton.article

1 голос
/ 03 февраля 2009

Есть ли какой-нибудь способ форсировать создание глобального объекта перед загрузкой DLL?

Как насчет опции DELAYLOAD? Чтобы библиотеки DLL не загружались до их первого вызова?

0 голосов
/ 29 марта 2012

Решение проблемы оказалось более простым, чем я изначально думал. Проблема порядка инициализации была вызвана существованием нескольких глобальных переменных типов, производных от типов контейнеров std (основной недостаток дизайна, который предшествовал моей позиции в этой компании). Решение состояло в том, чтобы заменить все такие глобалы синглетами. Их было около 100 человек.

Как только это было сделано, порядок инициализации (и уничтожения) был под контролем программиста.

0 голосов
/ 04 февраля 2009

Как насчет этого,

  1. Сделайте вашу основную программу тоже DLL, назовите ее main.dll, связав ее со всеми остальными, и экспортируйте основную функцию, скажем, mainEntry (). Удалить глобальную переменную.
  2. Создайте новый основной exe-файл, который имеет глобальную переменную и его инициализацию, но не статически связан с какой-либо другой DLL-библиотекой приложения (кроме распределителя).
  3. Этот новый main.exe затем динамически загружает main.dll с помощью LoadLibrary (), затем использует GetProcAddress для вызова mainEntry ().
0 голосов
/ 31 октября 2008

Это, безусловно, интересная проблема. У меня нет другого решения, кроме как, возможно, изменить дизайн так, чтобы не было зависимости от неопределенного поведения заказа или запуска link / dll. Рассматривали ли вы ссылку на старый линкер? (или каков бы ни был термин VS.NET)

Поскольку поведение вашей переменной и распределителя зависит от некоторого (неизвестного в то время) произвольного порядка запуска, я, вероятно, исправлю это, чтобы в будущем это не было проблемой. Я думаю, вы действительно спрашиваете, знает ли кто-нибудь, как сделать вуду в VC9, чтобы проблема исчезла. Мне тоже интересно это услышать.

...