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 文件中添加一行:
<Import Project="$(SolutionDir)SolutionSettings.props" />
我不确定是否有更“有力”的方式来确保新项目具有“正确”的默认值。
【讨论】:
【参考方案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 2019 中启用编译器警告?
如何更改 Visual Studio 10 中的编译器选项?