我可以在Visual Studio 2008的C++运行时库中使用Visual Studio 2010的C++编译器吗?

Bil*_*eal 36 c++ visual-studio-2008 visual-studio

我有一个需要在Windows 2000上运行的应用程序.我还想使用Visual Studio 2010(主要是因为auto关键字定义的更改).但是,我有点绑定,因为我需要应用程序能够在较旧的操作系统上运行,即:

  • Windows 2000
  • Windows XP RTM
  • Windows XP SP1

Visual Studio 2010的运行时库依赖EncodePointer / DecodePointer于Windows XP SP2中引入的API.

如果可以使用备用运行时库,那么这会破坏依赖于VS2010中添加的C++ 0x功能的代码std::regex吗?

Ash*_*ain 24

最简单的解决方案是将VS2010中的项目设置中的Platform Toolset设置为v900,它将使用Visual Studio 2008库和编译器.这也意味着你失去了C++ 0x的功能auto,但说实话,使用某些方法解决这个问题typedef可能比构建自己的CRT版本或其他更复杂的解决方案更容易.或者,只需使用VS2008!我不知道是否有其他C++ 0x功能对您的应用程序至关重要,但您没有提及 - 除了std::regex我认为仍然在技术报告1名称空间(std::tr1::regex)下的v900工具集中.

从我得到的印象来看,我预测让VS2010库在XP SP1上运行的不便大于C++ 0x功能的便利性,所以整体来说它不值得.

  • 我同意.提出的其他解决方案是"酷",这就是问题所在.我不敢运送带有这种"酷"黑客的产品.如果事情没有成功怎么办?这将是调试和追踪的地狱.我喜欢汽车,lambdas,r值参考和decltype和下一个人一样多但不惜任何代价. (3认同)

Sum*_*uma 24

您不能使用2008 CRT,但可以阻止从内核链接新功能DecodePointer/EncodePointer.用存根替换新函数非常容易.

有人可能会尝试跟随:在main.cpp源代码中放置这样的代码:

extern "C" {

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

};
Run Code Online (Sandbox Code Playgroud)

以上不起作用.虽然基本思想是合理的,但执行需要有点不同.正如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
Run Code Online (Sandbox Code Playgroud)

项目中的符号优先于库中的任何符号.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 ... 
Run Code Online (Sandbox Code Playgroud)

这表明在一些CRT中使用了新的API,以便为一些被认为提供频繁攻击向量的功能提供更高的安全性.

通过一些努力,可以使用LoadLibrary/GetProcAddress来提供OS提供的真实功能,但我认为它不会真正带来任何东西.使用DecodePointer/EncodePointer的运行时函数并不真正需要它来提供任何编码,他们只需要通过对称进行编码.您并不真正需要增强的安全性(VS 2008运行时也不会提供给您).

我希望没有其他障碍等着你 - 我无法访问Win2k或XP pre SP2系统,因此我无法尝试.如果有任何exe标头标志阻止甚至试图在这样的系统上启动exe,它们应该很容易更改.

  • 如果本网站上的所有[默认许可](http://creativecommons.org/licenses/by-sa/3.0/)不够自由:在法律允许的范围内,我,OndřejŠpaněl,已放弃所有版权以及此答案中相关或相邻的代码权限. (5认同)
  • +1,整洁和*相对*干净的解决方案.自从vs2005以来,MS一直在添加(imho不必要)"杀掉旧Windows"支持的东西很烦人. (2认同)
  • 麻烦,这当然行不通 - __imp_*是函数的双字指针.生成的代码有效地将De/EncodePointer函数的机器代码解释为指针并尝试调用该内存位置.您需要生成指向虚拟函数的__imp_*指针. (2认同)
  • @Suma:您是否愿意在BSD风格或类似(自由)许可下发布您的实施?虽然在我的[我的OSS项目](https://bitbucket.org/BillyONeal/instalog)中获得了BSD和BSL许可,但我在这里复制你的代码感觉不舒服.(我不想对客户施加额外的许可要求) (2认同)

sne*_*rch 11

Suma的解决方案看起来非常有前景,但它不起作用:__imp__*@4符号需要指向函数,而不是函数本身.不幸的是,我不知道如何让Visual C++吐出一个带有这种名称生成的指针...(好吧,__declspec(naked)结合使用__stdcall的技巧,但后来我不知道如何发出指针).

如果在构建时使用汇编程序是可以的,那么解决方案非常简单 - 使用FASM汇编以下代码并链接到生成的目标文件,并且presto - exe中没有EncodePointer/DecodePointer引用:

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
Run Code Online (Sandbox Code Playgroud)


Tom*_*lny 8

由于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
Run Code Online (Sandbox Code Playgroud)

并记住将Linker-> System-> Minimum Required Version设置为5.0(默认为5.1)以在Windows 2000上运行.