【问题标题】:How to catch exceptions conditionally?如何有条件地捕获异常?
【发布时间】:2015-05-12 00:06:53
【问题描述】:

我的大型应用程序有这样的结构:

int main()
{
    try {
        ...
    } catch (std::exception& e) {
        std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
        return 1;
    }
}

在调用堆栈的深处,各种对象检查它们的内部状态,如果它们检测到错误,则抛出std::runtime_exception。包罗万象的异常处理程序会捕获它,打印一些适度有用的信息并终止程序。

但是,当我在 MS Visual Studio 下调试时,我可以从没有任何异常处理程序中受益:Visual Studio 有自己的非常有用的处理程序,它会在引发异常的地方停止我的应用程序,所以我可以检查出了什么问题。

如何有条件地捕获我的异常?

我尝试了以下方法:

    try {
        ...
    } catch (std::exception& e) {
        if (IsDebuggerPresent())
            throw;
        else
            std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
    }

这给出了一个奇怪的结果:Visual Studio 捕获了被重新抛出的异常,并向我显示了抛出异常时的堆栈跟踪。但是,我的应用程序中的所有对象显然都被破坏了,我看不到例如局部变量或成员变量。

我可以使异常处理程序以编译标志为条件:

#ifdef NDEBUG
    try {
#endif
        ...
#ifdef NDEBUG
    } catch (std::exception& e) {
        std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
    }
#endif

但这很不方便,因为如果我想调试它,我必须重新编译所有东西。

那么,我怎样才能使我的异常处理有条件(例如,取决于命令行参数)?

【问题讨论】:

  • 尝试Debug -> Exceptions 并勾选“Break on throw”框以获取您想要捕获的异常。
  • 更好的方法是有条件地抛出一个你的处理程序根本无法捕获的异常(通过间接级别),让调试器来抢夺'时间。
  • 如果@CompuChip 的方法适合你,那绝对是这两个中更好的。

标签: c++ visual-studio debugging exception


【解决方案1】:

那么,我怎样才能使我的异常处理有条件(例如,取决于命令行参数)?

通过为它编写代码:o]

考虑这个原始代码:

int main()
{
    try {
        run_the_application(); // this part different than your example
    } catch (std::exception& e) {
        std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
        return 1;
    }
}

新代码:

template<typename F>
int fast_run(F functor) { functor(); return EXIT_SUCCESS; }

template<typename F>
int safe_run(F functor)
{
    try {
        functor();
    } catch (std::exception& e) {
        std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

template<typename F>
int run(const std::vector<std::string>& args, F functor)
{
    using namespace std;
    if(end(args) != find(begin(args), end(args), "/d"))
        return fast_run(functor);
    else
        return safe_run(functor);
}

int main(int argc, char** argv)
{
    const std::vector<std::string> args{ argv, argv + argc };
    return run(args, run_the_application);
}

【讨论】:

    【解决方案2】:

    正如CompuChip 所建议的,Visual Studio 可以在抛出异常时中断执行,而不仅仅是在捕获未捕获的异常时!

    启用此功能(在 Visual Studio 2012 中):

    1. 在菜单中,转到调试 -> 异常
    2. 在打开的窗口中,勾选所有 C++ 异常的“抛出”框(仅勾选 std::exception 是不够的 - 我不知道为什么)
    3. 运行你的程序

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-11
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 2015-02-19
      • 2013-12-22
      • 1970-01-01
      相关资源
      最近更新 更多