在混合C和C++代码中,捕获异常后对象未被销毁,这是为何?

2026-04-16 19:214阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计410个文字,预计阅读时间需要2分钟。

在混合C和C++代码中,捕获异常后对象未被销毁,这是为何?

我正在使用C++编写程序,在C异常处理程序中遇到了有关对象破坏的问题。我编写了一个简单的例子来重现这个问题。在main.cpp中:

我正在使用混合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不是.

在混合C和C++代码中,捕获异常后对象未被销毁,这是为何?

本文共计410个文字,预计阅读时间需要2分钟。

在混合C和C++代码中,捕获异常后对象未被销毁,这是为何?

我正在使用C++编写程序,在C异常处理程序中遇到了有关对象破坏的问题。我编写了一个简单的例子来重现这个问题。在main.cpp中:

我正在使用混合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不是.

在混合C和C++代码中,捕获异常后对象未被销毁,这是为何?