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

发布于 2024-10-16 08:46:40 字数 2016 浏览 1 评论 0原文

背景

我正在从命令行使用 CLLINK 构建一个由本机 C++、混合 C++/CLI 和安全 C++/ 组成的项目命令行界面。我需要以 .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:通过引用返回无法验证:在基本块中找不到返回本地的定义

第二个用于 PtrToStringChars来自 Microsoft 头文件,该文件允许您使用 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%

Background

I am using CL and LINK from the command line to build a project composed of native C++, mixed C++/CLI, and safe C++/CLI. I need to target .NET Framework 2.0-3.5 so I am using the VC90 toolchain (I have VS2010 but installed VS2008 C++ express and the SDK for Windows 7 and .NET 3.5 SP1 to get the complete VC90 toolchain).

If I try my script with the VS100 toolchain it works fine but targets .NET v4.0. If I don't use /GL for my native and mixed code it works. I know of these solutions, so don't suggest them. I am trying to understand why this is occurring.

Problem

If I use /GL and /LTCG I get many of the following warnings in the native code:

xxx.cpp(###) : warning C4748: /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function

And the following error in the mixed code:

c:\program files (x86)\microsoft visual studio 9.0\vc\include\vcclr.h(47) : error C4801: Return by reference is not verifiable: definition of returned local not found in basic block

The second one is for PtrToStringChars from a Microsoft header file that allows you to use a String^ as const wchar_t* and is a function that MUST be inlined (and is marked inline). The "return by reference" won't actually be a return when inlined, thus no error.

The issue is that I do use optimizations while compiling! I use the standard /O2 which has the highest level of inlining (/Ob2) and normally allows /GS.

Script

Here is my abridged compilation script

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%

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时常饿 2024-10-23 08:46:40

简短版本:在代码验证程序执行可访问性检查之后,MSIL 中的内联发生在 JIT 期间。

长版本:

全程序优化不适用于 MSIL,因为 MSIL 始终跨编译单元进行优化,并且甚至跨程序集(除非通过调试关闭优化)。我认为这就是您发出警告的根源。

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

PtrToStringChars 的使用与 /clr 不兼容:安全,因为它不可验证。不过,对于 /clr 应该没问题,对于 /clr:pure 也应该没问题,因为它们都不会尝试创建可验证的程序集。如前所述,在 /clr 模式下编译时,不允许编译器内联。这就是你的错误的根源。

最后一个问题是网络模块的创建。我非常确定混合模式代码必须创建为成熟的程序集而不是网络模块。

Short Version: Inlining in MSIL takes place during JIT, after the code verifier performs accessibility checking.

Long Version:

Whole-Program Optimization doesn't apply to MSIL, because MSIL always gets optimized across compile units, and even across assemblies (unless optimizations are turned off by debug). I think this is the source of your warnings.

Many optimizations are the responsibility of the JIT, including inlining. Coupled with accessibility checks, this prevents the C++ compiler from running an inlining pass on MSIL. (What happens if a member function using private members get inlined in native C++? Not much. What happens if a member function using private members gets inlined in MSIL into a function that has no access to those private members? The .NET runtime throws an absolute fit. Everything you think you know about compiler settings for inlining just doesn't apply to MSIL.) This is why...

...use of PtrToStringChars is incompatible with /clr:safe because it isn't verifiable. It should be fine with /clr though, and also with /clr:pure since neither of those try to create verifiable assemblies. As mentioned, the compiler is not allowed to inline when compiling in /clr modes. This is the source of your error.

A final problem is creation of a netmodule. I'm pretty sure that mixed-mode code has to be created as full-blown assemblies and not netmodules.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文