当我从 /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/