我正在使用混合c和c编写程序,我在c异常处理程序中遇到了有关对象破坏的问题.我写了一个简单的案例来重现这个问题. main.cpp中 #include iostreamextern "C" void test(void(*f)(void));struct foo { ~foo
main.cpp中
#include <iostream> extern "C" void test(void(*f)(void)); struct foo { ~foo() { std::cout << "foo destruction" << std::endl; } }; void error_handler(void) { throw 1; } int main() { try { foo f; test(error_handler); } catch (...) { } }
test.c的
void test(void(*handler)(void)) { handler(); }
当我在Visual Studio 2015和Visual Studio 2017中构建它时,没有调用foo的析构函数.但是当我使用gcc 5.4测试它时,foo的析构函数工作正常.
是否可以通过调用函数指针(指向cpp代码中实现的函数的指针)在C代码中抛出C异常?上面的代码是非法的还是只是一个msvc错误?
Windows异常机制明确设计为能够运行析构函数并执行最终类型清理,即使存在异常和类似的其他语言.因此,您所要求的应该在Windows上正常工作 – 它的设计目的.
但是,您需要在Visual Studio中显式启用它.默认情况下,visual studio使用/ EHsc异常模型设置C代码,该模型明确假设extern“C”函数不抛出或通过异常.这是一种优化,通常是一种很好的优化.
但是,如果您需要假设extern“C”函数抛出或传递异常,那么您需要更改异常模型.你可能想要/ EHs.
但是,我建议您在更改它之前了解它的后果here.
编辑:是否使用此功能是值得商榷的.通常使用异常(和其他类似机制),thrower和调用者之间的堆栈上的所有代码都必须是异常安全的.如果您拥有代码,那么这很好,如果有类似Windows回调或堆栈上的其他库,那么您需要找到保证这是正常的.一般来说,windows internal code不是.