LTCG不记得在编译时指定了/ O2

时间:2011-02-05 06:39:04

标签: visual-c++ optimization c++-cli

背景

我在命令行中使用CLLINK来构建一个由本机C ++,混合C ++ / CLI和安全C ++ / CLI组成的项目。我需要针对.NET Framework 2.0-3.5,所以我使用VC90工具链(我有VS2010,但安装了VS2008 C ++ express和用于Windows 7和.NET 3.5 SP1的SDK以获得完整的VC90工具链)。

如果我使用VS100工具链尝试我的脚本它可以正常工作,但目标是.NET v4.0。如果我不使用/GL作为我的原生代码和混合代码,那么它可以工作。我知道这些解决方案,所以不要暗示它们。我试图理解为什么会这样。

问题

如果我使用/GL/LTCG,我会在本机代码中收到以下许多警告:

  

xxx.cpp(###):警告C4748:/GS无法保护参数和局部变量不受本地缓冲区溢出的影响,因为在函数中禁用了优化

混合代码中出现以下错误:

  

c:\ program files(x86)\ microsoft visual studio 9.0 \ vc \ include \ vcclr.h(47):错误C4801:按引用返回不可验证:基本块中找不到返回本地的定义

第二个是来自Microsoft头文件的PtrToStringChars,它允许您使用String^作为const wchar_t*,并且是一个必须内联的函数(并标记为内联)。内联时“返回引用”实际上不是返回,因此没有错误。

问题是我在编译时会使用优化!我使用标准/O2,它具有最高级别的内联(/Ob2),通常允许/GS

脚本

这是我的简略编译脚本

set TARGET=x86
call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" %TARGET%

set CL=/nologo /Zl /Zi /W4 /O2 /Oy- /GL /GS /EHa /MP /D NDEBUG /D _UNICODE /D UNICODE /D INTEGRATED /Fdout\ /Foout\
set LINK=/nologo /LTCG /CLRIMAGETYPE:IJW /MACHINE:%TARGET% /SUBSYSTEM:WINDOWS,6.0 /OPT:REF /OPT:ICF /DEFAULTLIB:msvcrt.lib /DEFAULTLIB:msvcmrt.lib
set CSC=/nologo /w:4 /d:INTEGRATED /o+ /target:module

set CL_NATIVE=/c /FI"stdafx-native.h"
set CL_MIXED=/c /clr /LN /FI"stdafx-mixed.h"
set CL_PURE=/c /clr:safe /LN /GL /FI"stdafx-pure.h"

set NATIVE=a.cpp b.cpp ...
set MIXED=c.cpp d.cpp ...
set PURE=e.cpp f.cpp ...

cl %CL_NATIVE% %NATIVE%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%

cl %CL_MIXED% %MIXED%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%

cl %CL_PURE% %PURE%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%

link /LTCG /NOASSEMBLY /DLL /OUT:"out\x.netmodule" out\*.obj
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%

1 个答案:

答案 0 :(得分:2)

简短版本:在代码验证程序执行辅助功能检查后,在JIT期间进行内联调用。

长版:

整个程序优化不适用于MSIL,因为MSIL总是在编译单元之间进行优化,甚至跨程序集进行优化(除非通过调试关闭优化)。我认为这是你警告的来源。

许多优化是JIT的责任,包括内联。与可访问性检查相结合,这可以防止C ++编译器在MSIL上运行内联传递。 (如果使用私有成员的成员函数在本机C ++中内联会发生什么?不多。如果使用私有成员的成员函数在MSIL中内联到一个无法访问这些私有成员的函数会发生什么?.NET运行时抛出一个绝对适合。你认为你所知道的关于内联编译器设置的一切都不适用于MSIL。)这就是为什么......

...使用PtrToStringChars/clr:safe不兼容,因为它无法验证。但是/clr/clr:pure都应该没问题,因为它们都没有尝试创建可验证的程序集。如上所述,在/clr模式下编译时,不允许编译器内联。这是您的错误来源。

最后一个问题是创建一个netmodule。我很确定混合模式代码必须创建为完整的程序集,而不是netmodules。