如何有条件地捕获异常?
How to catch exceptions conditionally?
我的大型应用程序具有以下结构:
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
但这很不方便,因为如果我想调试它,我必须重新编译所有东西。
那么,如何使我的异常处理有条件(例如,取决于命令行参数)?
So, how can I make my exception handling conditional (depending on a command-line argument, for example)?
通过为其编写代码: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);
}
正如 所建议的那样,Visual Studio 可以在抛出异常时中断执行,而不仅仅是在捕获未捕获的异常时!
要启用此功能(在 Visual Studio 2012 年):
- 在菜单中,转到调试 -> 异常
- 在打开的 window 中,勾选所有 C++ 异常的 "Thrown" 框(只勾选
std::exception
是不够的 - 我不知道为什么)
- 运行 你的程序
我的大型应用程序具有以下结构:
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
但这很不方便,因为如果我想调试它,我必须重新编译所有东西。
那么,如何使我的异常处理有条件(例如,取决于命令行参数)?
So, how can I make my exception handling conditional (depending on a command-line argument, for example)?
通过为其编写代码: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);
}
正如
要启用此功能(在 Visual Studio 2012 年):
- 在菜单中,转到调试 -> 异常
- 在打开的 window 中,勾选所有 C++ 异常的 "Thrown" 框(只勾选
std::exception
是不够的 - 我不知道为什么) - 运行 你的程序