代码之家  ›  专栏  ›  技术社区  ›  gauss256

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

  •  8
  • gauss256  · 技术社区  · 17 年前

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

    try {
      // some code that throws a std::exception
    }
    catch (std::exception &e) {
      // handle the exception
    }
    

    问题是这些异常没有被捕获,我也不知道为什么。

    代码编译到OS X中的静态库(通过Xcode)。该库链接到一个Cocoa应用程序,通过Objective-C++thunk调用相关函数。我怀疑ObjuleC和C++之间的相互作用是罪魁祸首,但是我所有的努力都失败了。

    我无法创建一个简单的示例,在一个简单的示例中重现这种行为。当我把相关的代码从我的大程序中去掉时,一切都会正常工作。

    有人能告诉我为什么我的例外没有被抓住吗?

    8 回复  |  直到 13 年前
        1
  •  16
  •   Michael F    17 年前

    试一试 catch(...) {} 块,查看是否确实引发了异常。

        2
  •  16
  •   Bill    13 年前

    C++ allows you a variety of options for catching: value, reference or pointer. 请注意,此代码只捕获引用或值传递的std::exceptions:

    try {
      // some code that throws a std::exception
    }
    catch (std::exception &e) {
      // handle the exception
    }
    

    很可能是指针传递了异常:

    catch (std::exception* e)
    

    检查引发异常的代码,看看它是如何处理的。

    正如马克指出的那样,如果你以值而不是参照来捕捉,你就有可能把你的对象切片。

        3
  •  7
  •   Max Lybbert    17 年前

    我怀疑ObjuleC和C++之间的相互作用是罪魁祸首,但是我所有的努力都失败了。

    你可能是对的,尽管很难找到。

    首先,GCC明确 does not allow you to throw exceptions in Objective C++ and catch them in C++ ()当从ObjuleC++中使用时,ObjtoE-C异常模型此时不会与C++异常互通。这意味着你不能 @throw 目标C和 catch 它在C++中,反之亦然。 throw … @catch “”

    但是,我认为你正在描述一个实例,其中目标C++调用C++代码,C++代码抛出,希望C++代码捕获异常。不幸的是,我很难找到这个特定案例的文档。有希望,因为,” It is believed to be safe to throw a C++ exception from one file through another file compiled for the Java exception model, or vice versa, but there may be bugs in this area 如果他们能为Java做这件事,那么他们有可能为目标C++做这件事。

    至少,您需要指定 -fexceptions 在编译时(“编译C代码需要与C++编写的异常处理程序进行适当的操作时,您可能需要启用此选项”)。同样,这并没有具体提到目标C++,但它可能适用。

        4
  •  5
  •   Richard Corden    17 年前

    一个鲜为人知的带有异常的gotcha与基类的访问有关。

    如果你真的要抛出一个类 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;
      }
    }
    

    通常,这样的处理程序顺序将导致永远不会选择“b”处理程序,而是 这 case“b”私下与“a”冲突,因此不考虑类型“a”的catch处理程序。

        5
  •  3
  •   Martin v. Löwis    17 年前

    我可以提供两种理论:

    1. 异常会在catch子句出现之前被捕获;堆栈上的任何函数都可能是罪魁祸首。正如迈克尔建议的,试着抓住一切。
    2. 异常展开无法找到处理程序。要更详细地分析这一点,您必须逐步执行异常展开代码,这是非常复杂的。查看是否使用 -fobjc-exceptions 帮助。
        6
  •  1
  •   Adrian Grigore    17 年前

    这可能是一个长期的尝试,但在Visual Studio的编译器设置中,有一个选项可以完全关闭异常。也许在gcc/xcode中有类似的东西。

        7
  •  0
  •   Igor Zevaka    17 年前

    C++异常可以是任何事情,非常常见。 char* . 如前所述添加 catch (...) 至少让它断裂看看发生了什么。

        8
  •  -2
  •   gauss256    17 年前

    谢谢大家的意见。对于遇到类似问题的人来说,这些都是很好的建议。它现在起作用了,但我不能百分之百地确定我所做的各种改变中的哪一个使事情重新变得理智了。再一次,简化到有用的东西,并从那里建立备份的方法得到了回报。

    响应中没有提到的一件事,我认为这是我困惑的一部分,就是确保处理程序使它明显地捕捉到异常。我认为在我对处理程序的一些公式中,它掩盖了这个事实,并将异常传递给更高级别的处理程序。