Visual Studio:如果启用了编译器选项,如何测试(在代码/静态断言中)

Posted

技术标签:

【中文标题】Visual Studio:如果启用了编译器选项,如何测试(在代码/静态断言中)【英文标题】:Visual Studio: How to test (in code / static_assert) if a compiler option is enabled 【发布时间】:2021-01-27 00:23:13 【问题描述】:

我想在代码中检查某些选项是否在编译时设置。

具体来说,我已经实现了一些异常处理,并希望使用 static_assert 来确保在 Visual Studio 编译器中设置了 /EHa 选项。 (我使用的是启用 C++Latest 的 2017 和 2019)

我的解决方案有 54 个项目,每个项目有 4 个配置......很容易错过一个。 或者......如果未设置该选项,我可能希望代码有所不同......

非常感谢

【问题讨论】:

过去,我会像 cl /EHa /O3 -DCL_OPTS="/EHa /O3" foo.cpp 这样编译我的代码,然后我可以在我的代码中使用 CL_OPTS 宏。可能有一种我不知道的 CL.EXE 方式,但这是我的权宜之计。 看看docs.microsoft.com/en-us/cpp/preprocessor/… 搜索 54 个.vcxproj 文件对于任何体面的文本编辑器来说应该是一项轻而易举的任务。但将通用构建选项放入共享的.props 文件会更有意义。 @Eljay 谢谢当然是一个选项。 @Richard-Critten 谢谢。 _CPPUNWIND 是唯一一个看起来很有希望的,但即使使用其他 /EH 选项,它也被定义为(1) 【参考方案1】:

当我使用这些选项时,我确实发现编译器已经为此发出警告:warning C4535: calling _set_se_translator() requires /EHa

我查看了这是否是 VS 标头中函数的属性或装饰器,因此我可以将其直接移植到我的代码中,但找不到任何东西。

到目前为止,我已决定在代码中添加注释,以供其他开发人员查看何时发出警告。

// Save & Restore the Structured Exception Handler
// Set our own handler during the call
class Scoped_SE_Translator

private:
    const _se_translator_function old_SE_translator;
public:
    Scoped_SE_Translator() = delete;
    Scoped_SE_Translator(_se_translator_function new_SE_translator) noexcept :  // NOTE: Compiler option /EHa is required  ("Enable C++ Exception" = "Yes with SEH Exceptions")
        old_SE_translator_set_se_translator(new_SE_translator)  
    ~Scoped_SE_Translator() noexcept  _set_se_translator(old_SE_translator); 
;

我还在现有的 solution.props 文件中设置了项目默认值:

  <ItemDefinitionGroup>
    <ClCompile>
      <ExceptionHandling>Async</ExceptionHandling>
      <FloatingPointExceptions>true</FloatingPointExceptions>
      <TreatSpecificWarningsAsErrors>4535;%(TreatSpecificWarningsAsErrors)</TreatSpecificWarningsAsErrors>
    </ClCompile>
  </ItemDefinitionGroup>

但是,这取决于开发人员在新的 vcxproj 文件中添加一行:

&lt;Import Project="$(SolutionDir)SolutionSettings.props" /&gt;

我不确定是否有更“有力”的方式来确保新项目具有“正确”的默认值。

【讨论】:

【参考方案2】:

我建议您可以使用 [预定义宏(https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-160)。

_CPPUNWIND:如果 /GX(启用异常处理)、/clr(公共语言运行时编译)或 /EH 中的一个或多个,则定义为 1 (异常处理模型)编译器选项已设置。除此以外, 未定义。

另外,您可以参考 Microsoft Docs 关于To set this compiler option programmatically。

此外,您还可以使用代码来确定是否启用了 /EHa。例如:

inline bool CodeHasEHaSwitch()

    bool dtorCalled = false;

    struct CCheckEHaSwitch
    
        CCheckEHaSwitch( bool& dtorCalled) : dtorCalled( dtorCalled ) 
        ~CCheckEHaSwitch()   dtorCalled = true; 
        bool& dtorCalled;

        static void Win32ExceptionTranslator( unsigned int nExceptionCode,
        EXCEPTION_POINTERS *pExceptionInfo )
          throw nExceptionCode; 
    ;

    _se_translator_function pfnPrevSeTranslator =
        _set_se_translator( CCheckEHaSwitch::Win32ExceptionTranslator );
    try
    
        CCheckEHaSwitch test( dtorCalled );

        *((int*)0) = 0;  // generate access violation
    
    catch (unsigned int)
    
    

    _set_se_translator( pfnPrevSeTranslator );

    return dtorCalled;

【讨论】:

感谢@Barrnet-Chou - 概念上的强大功能,但在运行代码之前你不会知道答案:-) 我检查了预定义,但 _CPPUNWIND 甚至被定义为 1对于其他/EH?选项。

以上是关于Visual Studio:如果启用了编译器选项,如何测试(在代码/静态断言中)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio 中启用 C++17 编译?

Visual Studio 2008 中的文件特定编译选项

如何在 Visual Studio 2019 中启用编译器警告?

如何更改 Visual Studio 10 中的编译器选项?

如何在 Visual Studio 中启用 NuGet 包还原?

Visual Studio - 并行化构建不会提高性能