为什么我的C++异常没有被捕获?

gau*_*256 8 c++ exception-handling objective-c

我有一些使用非常标准的异常模式的C++代码:

try {
  // some code that throws a std::exception
}
catch (std::exception &e) {
  // handle the exception
}
Run Code Online (Sandbox Code Playgroud)

问题是异常没有被捕获,我无法弄清楚原因.

代码编译为OS X中的静态库(通过Xcode).该库链接到一个Cocoa应用程序,通过Objective-C++ thunk调用所讨论的函数.我怀疑Objective-C和C++之间的相互作用是罪魁祸首,但我所有试图将其解决的尝试都失败了.

我无法创建一个简单的示例,在一个简单的示例中重现此行为.当我从大型程序的上下文中取出相关代码时,一切正常.

任何人都可以建议为什么我的例外没有被抓住?

Mic*_*kis 16

尝试一个catch(...) {}块,看看是否真的抛出异常.

  • 该问题包括`std :: exception`类型的异常处理程序.使用省略号(...)作为catch参数的catch块将捕获任何异常,无论抛出异常的类型是什么.很像"默认"处理程序. (3认同)

Bil*_*ill 16

C++允许您使用各种选项来捕获:值,引用或指针. 请注意,此代码仅捕获通过引用或值传递的std :: exceptions:

try {
  // some code that throws a std::exception
}
catch (std::exception &e) {
  // handle the exception
}
Run Code Online (Sandbox Code Playgroud)

指针可能会传递异常:

catch (std::exception* e)
Run Code Online (Sandbox Code Playgroud)

检查抛出异常的代码,看看它是如何做的.

正如马克指出的那样,如果你按价值而不是通过参考捕获,你就有可能切割你的对象.

  • @BenL:我_highly_建议不要用指针投掷.按值引用并通过const引用捕获. (4认同)
  • 对不起,这个答案错了​​.您可以通过值或引用捕获异常,但它总是按值抛出* - "catch"将正常工作.通过引用捕获是首选,以防止异常对象切片.抛出一个指针是完全不同的事情,因为`std :: exception*`是一个完全不同于`std :: exception`的类型. (3认同)

Max*_*ert 7

我怀疑Objective-C和C++之间的相互作用是罪魁祸首,但我所有试图将其解决的尝试都失败了.

你可能是对的,虽然很难找到.

首先,GCC明确地不允许你在Objective C++中抛出异常并用C++捕获它们("当从Objective-C++使用时,Objective-C异常模型此时不与C++异常互操作.这意味着你不能@throw例外来自Objective-C,catch它来自C++,反之亦然(即throw... @catch).")

但是,我认为您正在描述一个Objective C++调用C++代码,C++代码抛出并且您希望C++代码捕获异常的情况.不幸的是,我很难找到这个具体案例的文档.有一些希望因为," 通过为Java异常模型编译的另一个文件从一个文件抛出C++异常被认为是安全的,反之亦然,但这个领域可能存在缺陷." 如果他们可以为Java做,那么他们有可能为Objective C++做到这一点.

至少,您需要-fexceptions在编译时指定("在编译需要与使用C++编写的异常处理程序正确互操作的C代码时,您可能需要启用此选项").同样,这并没有特别提到Objective C++,但它可能适用.


Ric*_*den 5

一个鲜为人知的问题与异常有关,与基类的访问有关.

如果你实际上是在抛出一个私有派生的类,std::exception那么std::exception就不会选择处理程序.

例如:

#include <iostream>

class A { };
class B : private A { } ;

int main ()
{
  try
  {
    throw B ();
  }
  catch (A & )
  {
    std::cout << "Caught an 'A'" << std::endl;
  }
  catch (B & )
  {
    std::cout << "Caught an 'B'" << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

通常,这样的处理程序顺序会导致'B'处理程序永远不会被选中,但在这种情况下'B'私有地从'A'进行处理,因此不考虑类型'A'的catch处理程序.


gau*_*256 -2

感谢大家的意见。对于遇到类似问题的人来说,这些都是很好的建议。它现在可以工作了,但我不能 100% 确定我所做的各种改变中的哪一个导致事情再次变得理智。再一次,简化为可行的方法并从那里进行重建的方法得到了回报。

响应中没有提到的一件事(我认为这是我困惑的一部分)是确保处理程序明显表明它确实捕获了异常。我认为在我的处理程序的某些表述中,它掩盖了这一事实并将异常传递给更高级别的处理程序。