Можно ли использовать компилятор Visual Studio 2010 C ++ с библиотекой времени выполнения C ++ Visual Studio 2008? - PullRequest
36 голосов
/ 20 марта 2010

У меня есть приложение, которое должно работать в Windows 2000. Я также хотел бы использовать Visual Studio 2010 (в основном из-за изменения определения ключевого слова auto). Однако я немного затруднен, потому что мне нужно, чтобы приложение могло работать на старых ОС, а именно:

  • Windows 2000
  • Windows XP RTM
  • Windows XP SP1

Библиотека времени выполнения Visual Studio 2010 зависит от EncodePointer / DecodePointer API, который был представлен в Windows XP SP2.

Если возможно использование альтернативной библиотеки времени выполнения, будет ли этот код прерывания, основанный на функциях C ++ 0x, добавлен в VS2010, например std::regex?

Ответы [ 8 ]

24 голосов
/ 17 августа 2010

Вы не можете использовать 2008 CRT, но вы можете запретить связывание новых функций DecodePointer / EncodePointer из ядра. Заменить новые функции на заглушки довольно просто.

Можно попытаться сделать следующее: Поместите такой код в исходный код main.cpp:

extern "C" {

  void *__stdcall _imp__DecodePointer(void *x) {return x;}
  void *__stdcall _imp__EncodePointer(void *x) {return x;}

};

Выше не работает. В то время как основная идея - звук, исполнение должно быть немного другим. Как описано snemarch в комментарии и , другой ответ , __imp__ не может быть вызовом функции, только указатель на нее. Поскольку кажется невозможным сгенерировать указатель непосредственно компилятором, вам необходимо собрать следующий код с MASM и связать его с созданным объектным файлом.

.model flat

.data
__imp__EncodePointer@4 dd dummy
__imp__DecodePointer@4 dd dummy
EXTERNDEF __imp__EncodePointer@4 : DWORD
EXTERNDEF __imp__DecodePointer@4 : DWORD

.code
dummy proc
mov eax, [esp+4]
ret 4
dummy endp

end

Символы из проекта имеют преимущество перед любыми символами из библиотек. Библиотеки DLL связаны с использованием частей .lib, которые содержат только __imp__ «векторов», переходящих в реальные функции. Заменяя __imp__ «векторы», вы не касаетесь связывания DLL, вы заменяете часть .lib. Я убедился, что больше нет никакой зависимости exe-файла от DecodePointer / EncodePointer.

Фон

Статически связанная библиотека вносит в приложение только используемые функции. Можно найти, какую конкретную функцию CRT привнести в эти новые API, используя подробный вывод прогресса компоновщика:

Found __imp__EncodePointer@4
  Referenced in LIBCMT.lib(crtmboxw.obj)
  Referenced in LIBCMT.lib(invarg.obj)
  Referenced in LIBCMT.lib(handler.obj)
  Referenced in LIBCMT.lib(onexit.obj)
  Referenced in LIBCMT.lib(cmiscdat.obj)
  Referenced in LIBCMT.lib(tidtable.obj)
  Referenced in LIBCMT.lib(hooks.obj)
  Referenced in LIBCMT.lib(winsig.obj)
  Referenced in LIBCMT.lib(rand_s.obj)

Found __imp__DecodePointer@4
  // ... same list, only order differs ... 

Это показывает, что новые API используются в некоторых CRT для обеспечения большей безопасности для некоторых функций, которые, как считается, предоставляют частые векторы атак.

С некоторыми усилиями можно было бы использовать LoadLibrary / GetProcAddress, чтобы обеспечить реальную функциональность, в которой есть предложения ОС, но я не думаю, что это действительно что-то принесет. Функции времени выполнения, которые используют DecodePointer / EncodePointer, на самом деле не нуждаются в этом для обеспечения какой-либо кодировки, все, что им нужно, - это кодирование симметричным. На самом деле вам не нужна повышенная безопасность (среда выполнения VS 2008 также не предоставит ее вам).

Надеюсь, вас больше не ждут другие препятствия - у меня нет доступа к системе Win2k или XP pre SP2, поэтому я не могу попробовать. Если есть какие-либо флаги заголовка exe, предотвращающие даже попытку запуска exe в таких системах, их легко изменить.

24 голосов
/ 13 августа 2010

Самое простое решение - просто установить набор инструментов платформы в настройках проекта в VS2010 v900, который будет использовать библиотеки Visual Studio 2008 и компилятор. Это также означает, что вы теряете функции C ++ 0x, такие как auto, но, если честно, обойти это с некоторыми typedef s, вероятно, проще, чем создать собственную версию CRT или другие более сложные решения. В качестве альтернативы, просто используйте VS2008! Я не знаю, есть ли другие функции C ++ 0x, которые важны для вашего приложения, хотя вы не упомянули - кроме std::regex, который, я думаю, все еще находится в наборе инструментов v900 в пространстве имен технического отчета 1 ( std::tr1::regex).

Исходя из того, что у меня сложилось впечатление, я предполагаю, что неудобство запуска библиотек VS2010 на XP SP1 больше, чем удобство функций C ++ 0x, поэтому в целом оно того не стоит.

11 голосов
/ 27 августа 2010

Решение Suma выглядело довольно многообещающе, но оно не работает: символы __imp__*@4 должны быть указателями на функции, а не на сами функции.К сожалению, я не знаю, как заставить Visual C ++ выплевывать указатель с таким типом генерации имен ... (ну, __declspec(naked) в сочетании с __stdcall добивается цели, но тогда я не знаю, как излучатьуказатель).

Если использование ассемблера во время сборки в порядке, решение довольно тривиально - собрать следующий код с FASM и связать его с созданным объектным файломнет ссылок EncodePointer / DecodePointer в exe:

use32
format ms coff

section ".data" data
public __imp__DecodePointer@4
__imp__DecodePointer@4 dd dummy

public __imp__EncodePointer@4
__imp__EncodePointer@4 dd dummy

section ".text" code
dummy:
mov eax, [esp+4]
retn 4
8 голосов
/ 14 сентября 2010

Поскольку Visual Studio поставляется с поддержкой MASM (см. Свойства проекта -> Настройки сборки ...), может пригодиться следующий перевод кода snemarch в MASM:

.model flat

.data
__imp__EncodePointer@4 dd dummy
__imp__DecodePointer@4 dd dummy
EXTERNDEF __imp__EncodePointer@4 : DWORD
EXTERNDEF __imp__DecodePointer@4 : DWORD

.code
dummy proc
mov eax, [esp+4]
ret 4
dummy endp

end

И не забудьте установить Linker-> System-> Minimum Required Version на 5.0 (по умолчанию 5.1) для работы в Windows 2000.

4 голосов
/ 13 августа 2010

Обычное решение этой проблемы - создание собственной пользовательской версии CRT. Инструкции для этого здесь . Вам просто нужно отредактировать код, чтобы игнорировать EncodePointer и DecodePointer. (Для этого уже должно быть #define.)

Есть еще две незначительные вещи, которые вам нужно сделать:

  • Перейдите к настройке Linker-> Additional Library Directoryies и установите C:\Microsoft Visual Studio 9.0\VC\lib в качестве первого пути для поиска. (Я предполагаю, что вы использовали каталог установки по умолчанию, в противном случае измените соответствующим образом.)
  • Измените версию подсистемы в заголовке PE на 5,00 (используйте бесплатную CFF Explorer Suite , если у вас нет другого удобного инструмента для этого).

Это должно позволить вашей программе работать как в Windows 2000, так и в более поздних версиях.

3 голосов
/ 02 апреля 2010

Это было бы намного проще, если бы вам разрешали использовать DLL. По сути, напишите EXE, который вообще не требует никаких функций времени исполнения C, используя функцию linker / ENTRYPOINT. После того, как вы проверили, что ваши основные предварительные требования выполнены, и сообщили о любых проблемах пользователю через только предоставляемые Windows API, доступные во всех целевых ОС (например, MessageBox), затем вызовите LoadLibrary, чтобы запустить DLL, которая содержит основную часть вашей логики. , Эта DLL может использовать среду выполнения VS2010 как обычно. Вы даже можете избежать развертывания двух отдельных файлов, распаковывая DLL из ресурса, содержащегося в вашем главном .EXE при запуске. (Вы можете сделать это полностью в памяти, не записывая .DLL на диск, но не в том случае, если вы хотите использовать загрузчик Windows PE для исправления всего импорта).

3 голосов
/ 21 марта 2010

Вариант 1 - создайте модифицированную версию среды выполнения 2010, которая перенаправляет вызовы API проблем в предоставленную вами DLL. Я не знаю, насколько это легко или сложно - надеюсь, просто незначительная настройка таблицы символов, но это зависит от формата файла - и вы, скорее всего, столкнетесь с пунктом обратного инжиниринга лицензии, конечно .

Вариант 2 - Сравнить экспортированные символы в двух разных версиях библиотек времени выполнения. Если символы одинаковы, у вас хорошие шансы на совместимость - хотя никаких гарантий. Возможно даже, что форматы файлов lib отличаются.

Вариант 3 - Проверьте, можете ли вы получить доступ к источникам времени выполнения через MSDN или аналогичный, в частности, для создания исправленной версии.

Вариант 4. Проверьте, можете ли вы использовать компилятор 2010 года, но более старый компоновщик, возможно, настроенный в ваших решениях в качестве пользовательского этапа сборки. Опять же, это зависит от того, имеют ли файлы obj и lib одинаковый формат, но вы можете написать небольшую утилиту для исправления простых различий, таких как номера версий, в заголовке. У более старого компоновщика не должно быть проблем с компоновкой в ​​старшей среде выполнения - при условии, что объекты нового компилятора совместимы с ним.

Вариант 5 - сборка DLL в 2010 году, которые не нуждаются в собственном времени выполнения, но которые загружаются и размещаются приложением, созданным с использованием более старого компилятора. Достижение требования «без времени выполнения» для ваших библиотек DLL может означать, что многие из ваших библиотек должны быть встроены в хост-приложение, и вам может потребоваться предоставить свои собственные интерфейсы (через хост-приложение) для функций библиотеки, которые вам нужны для работы с - особенно с выделением памяти.

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

0 голосов
/ 29 апреля 2010

Создайте .LIB, который реализует отсутствующую функциональность, и свяжите его с опережением KERNEL32.LIB.

Вам нужно будет использовать опцию компоновщика /NODEFAULTLIB:kernel32.lib, чтобы вы могли поместить свой w2kcompat.libвпереди kernel32.lib.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...