当前位置 : 主页 > 编程语言 > c++ >

在混合C和C代码编程中捕获异常后,对象不会被销毁

来源:互联网 收集:自由互联 发布时间:2021-06-23
我正在使用混合c和c编写程序,我在c异常处理程序中遇到了有关对象破坏的问题.我写了一个简单的案例来重现这个问题. main.cpp中 #include iostreamextern "C" void test(void(*f)(void));struct foo { ~foo
我正在使用混合c和c编写程序,我在c异常处理程序中遇到了有关对象破坏的问题.我写了一个简单的案例来重现这个问题.

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不是.

网友评论