问题描述
我想在代码中检查是否在编译时设置了某些选项。
具体来说,我已经实现了一些异常处理,并希望使用 static_assert 来确保在 Visual Studio 编译器中设置了 /EHa 选项。 (我使用的是 2017 和 2019 并启用了 C++Latest)
我的解决方案有 54 个项目,每个项目有 4 个配置......很容易错过一个。 或者...如果未设置该选项,我可能希望代码不同....
非常感谢
解决方法
当我使用这些选项时,我确实发现编译器已经为此发出警告: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" />
我不确定是否有更“有力”的方法来确保新项目具有“正确”的默认设置。
,我建议您可以使用 [预定义宏(https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-160)。
_CPPUNWIND:如果 /GX(启用异常处理)、/clr(公共语言运行时编译)或 /EH 中的一个或多个,则定义为 1 (异常处理模型)编译器选项已设置。否则, 未定义。
此外,您可以参考有关 To set this compiler option programmatically 的 Microsoft Docs。
此外,您还可以使用代码来确定是否启用了 /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;
}