Visual Studio 如何有条件地捕捉异常?

rlcwz9us  于 2023-02-24  发布在  其他
关注(0)|答案(3)|浏览(389)

我的大型应用程序具有以下结构:

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

但是这很不方便,因为如果我想调试它,我必须重新编译所有的东西。
那么,我如何使我的异常处理成为有条件的(例如,取决于命令行参数)?

2guxujil

2guxujil1#

那么,我如何使我的异常处理成为有条件的(例如,取决于命令行参数)?
通过编写它的代码: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);
}
yhived7q

yhived7q2#

正如CompuChip所建议的,Visual Studio可以在抛出异常时中断执行,而不仅仅是在捕获未捕获的异常时!
要启用此功能(在Visual Studio 2012中):
1.在菜单中,进入调试-〉异常
1.在打开的窗口中,勾选所有C++异常的“Thrown”框(仅勾选std::exception是不够的-我不知道为什么)
1.运行您的程序

i7uq4tfw

i7uq4tfw3#

这不是什么好东西,但你可以在CMake中定义命令行参数(假设你使用它):

-DCATCH_ALL=true

然后,在CMakelists.txt中,您可以将其传播到C++宏:

if (CATCH_ALL)
  message("Some exceptions with not be caught")
  add_compile_definitions(CATCH_ALL)
else ()
  message("Trying to catch more exceptions to provide better diagnostics")
endif ()

最后,在代码中:

#ifdef CATCH_ALL
try {
#endif
  a = big_problematic_algorithm(problematic_parameter);
#ifdef CATCH_ALL
 } catch (const std::exception &err) {
  LOGF(WARN, "Crashed for the parameter %s: %s", problematic_parameter.c_str(), err.what());
 }
#endif

这是相当笨拙的,但如果不经常使用还可以,只在非常高的级别(处理完整的Web请求,用户操作,要处理的文件等)。如果崩溃不是在IDE中运行时发生的,它允许提供更好的诊断日志,如果你自己抛出这个异常,也可以恢复,所以知道如何恢复。
可以配置IDE来设置CMake参数。当在集成服务器上或从命令行构建时,这只是不激活对异常的其他处理。

相关问题