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

是否有理由使用catch-all子句:catch(…)呢?

  •  5
  • Alon  · 技术社区  · 15 年前

    try 
    {
      // some code 
    }
    catch (...)
    {
    
    }
    

    它有 总是 这是一种虐待。

    任何东西 由于异常处理程序无法知道它在处理什么,因此在大多数情况下,异常将显示为模糊的日志消息或一些不连贯的消息框。

    所以 catch(...)

    但是它仍然是用C++和其他语言实现的(java,C语言)实现了类似的机制。那么,在某些情况下,它的使用是合理的吗?

    8 回复  |  直到 7 年前
        1
  •  6
  •   MSalters    15 年前

    (1) 这句话不是真的

    (2) 毫无疑问,catch-all行为对于具有特定用途的线程非常有用。捕获失败允许线程报告失败。没有它,程序的其他部分需要处理线程消失的可能性。它还允许您登录 哪一个

        2
  •  5
  •   Pavel Minaev    15 年前

    然后立即重新催促 .

    在C++中,特别是在 catch(...)

        3
  •  4
  •   DrPizza    15 年前

    如果同样的例外 不是 抓到你了。。。不连贯的信息框。

    拥有 消息框(并调用自定义日志,保存崩溃转储,

    我认为在析构函数中也有catch(…)的合理使用。析构函数不能抛出--我的意思是,它们可以抛出,但是如果析构函数在堆栈展开过程中由于进行中的异常而抛出,那么程序将终止,因此它们不应该允许异常转义。一般来说,允许第一个异常继续解开比终止程序要好。

        4
  •  3
  •   atzz    15 年前

    除了其他海报已经说过的,我想提一个来自C++标准的好观点:

    如果在中找不到匹配的处理程序 程序,函数std::terminate() 被称为; 不管堆栈是否为空 在此之前,请 实施被剥夺 .

    这意味着main()和每个线程函数 必须

        5
  •  2
  •   Tomek Szpakowicz    15 年前
    1. try{…}在从代码调用的回调函数体周围需要catch(…) 这不理解C++异常(通常是C库)。

      否则,如果某些C++库使用抛出的异常,则不会从 异常,它可能会导致调用代码崩溃或损坏其内部状态。
      相反,您应该捕获此异常,并立即或立即完成程序 返回一些错误代码(意思是“我们注定要失败,我不知道为什么”),但这样更好 然后让C++异常通过。

    2. 因为否则线程失败会被忽略。

        6
  •  2
  •   GManNickG    15 年前

    catch(...) 在两种情况下对我很有用,这两种情况都是不合理的(我甚至记不起第二种情况)

    首先是我的整体应用程序安全性。在抛出不是从 std::exception main()

    int execute(void); // real program lies here
    
    int main(void)
    {
        try
        {
            return execute();
        }
        catch(const std::exception& e)
        {
            // or similar
            std::cerr << "Unhandled exception: " << e.what() << std::endl;
            return EXIT_FAILURE;
        }
        catch(...)
        {
            std::cerr << "Unknown exception!" << std::endl;
            return EXIT_FAILURE;
        }
    }
    

    现在,它只是在那里“以防万一”,而不是 真正地

    第二种用法可能是在析构函数或其他一些函数中,这些函数在允许异常传播之前需要进行手动管理。这也不是一个真正的理由,因为事情应该用RAII安全地清理自己。但我可能因为一些我想不起来的原因用过一两次,我也看不出有什么理由再这样做。

        7
  •  1
  •   Paul Hsieh    15 年前

    catch(…)允许您编写代码,在其中您可以合法地声明,即使您无法长期完全控制代码所依赖的子模块,您的代码也不会崩溃。你的声明等同于声明这个语义不能被使用,除非是作为一种滥用的手段。也许是这样,但在这个问题上,军事规格可能与您有所不同。

        8
  •  -2
  •   Will    15 年前

    catch(...) 如果没有其他语言中的finally子句,则必须:

    try {
      ...
    } catch(...) {
      cleanup...
      throw;
    }
    

    另一种选择——让堆栈对象“拥有”所有东西——通常代码更多,可读性和可维护性更低。平台API通常是C语言的,并且不能方便地捆绑在一起。

    从稳定性的角度来看,对于您无法控制或根本不信任的插件代码,它也很有用。这不会阻止他们崩溃,但可能会让事情变得更理智一点。