c++ - 如何创建一个最小的测试用例来展示/EHs 的成本?

标签 c++ visual-studio exception visual-studio-2019

当我从 /EHsc 切换 Visual Studio 2019 时,我正在尝试调查生成代码的差异。 (仅限结构化和 C++ 异常)到 /EHs (也不要假设 extern "C" 函数不会抛出 - ref ),但是当我最小化它时,我似乎无法哄骗 VS 提供有用的测试用例。

我很惊讶the following doesn't do it (两种情况下的程序集是相同的),因为 fptr 引用的函数的内容(可能的定义包含在说明中的注释中)对于优化器来说是未知的。

void foo();

/*void foo()
{
    throw 0;
}*/

extern "C"
void bar(void (*fptr)())
{
    fptr();
}

int main()
{
    try
    {
        bar(&foo);
    }
    catch (...) {}
}

当然,它知道任何假设的异常都会立即被捕获,并且因为使用 /EHsc这种异常传播的结果对于 Microsoft 来说是“未定义的”,它“似乎可以工作”当然是一个有效的结果。但这对我没有多大帮助!

那么如何在不引入不同翻译单元的情况下进行这个实验呢?理想情况下,我希望能够为此提供一个 Compiler Explorer 片段。

我的目标是证明允许 extern "C"以明确定义的方式抛出(或者更确切地说,传播)C++ 异常不会比我愿意接受的交易成本更高。

是的,我知道 general advice不要让异常跨越模块边界或流经第三方 C 代码。是的,I am doing that anyway .是的,这在我们的项目中很好! 😊

最佳答案

下面的 MCVE 可能会给你一些关于测试框架的想法。您可以轻松添加更多“彻底”的测试代码,但这将编译和运行。请注意,使用 /EHsc选项集,会生成此警告:

warning C5039: 'FuncTst': pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception.



但是,当使用 /EHs警告消失了——这至少表明了不同代码生成的可能性。

这是建议的代码:

#pragma warning(disable:4514) // These two lines de-fluff the hundreds of other
#pragma warning(disable:4710) // warning generated when /Wall is used.

#include <iostream>

using pFunc = int(__stdcall*)(int);

extern int __stdcall FuncOne(int p) {
    int answer = 0;
    for (int i = 0; i < p; ++i) answer += i / p; // Possible divide-by-zero
    return answer;
}

extern "C" int __stdcall FuncTst(int i, pFunc fnc) noexcept // Expects noexcept but "FuncOne" can throw!
{
    return fnc(i);
}

int main()
{
    int q;
    std::cout << "Enter test number: ";
    std::cin >> q;
    int z = FuncTst(q, FuncOne);
    std::cout << "Result = " << z << std::endl;
    return 0;
}

希望能帮助到你!随意提供批评和/或要求任何“改进”或解释。

注意:虽然您不能专门启用 C5039使用(比如说)\W4 编译时发出警告,您可以强制将其标记为错误(尽管这可能有点苛刻),其中:

#pragma warning(error:5039)

关于c++ - 如何创建一个最小的测试用例来展示/EHs 的成本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59031290/

相关文章:

c++ - 编译器将如何优化临时对象?

c# - VS2010如何在installer中打包DB文件

actionscript-3 - ActionScript 冲突 : solving exceptions and strange cases

java - 如何处理 ifPresent 内部的异常?

c# - 从 C# 调用 C++ dll 时如何获取 std::exception 错误描述

c++ - 指向重载类型转换运算符的指针?

c++ - 多个字符串异常处理

c++ - 如何使 Visual Studio 2015 C++ 项目与 Visual Studio 2010 兼容?

c# - WIX ComponentGroup 子目录

c++ - 如何在不包含 cmath 库的情况下使用 pow