我们使用的API非常依赖异常来返回非异常结果。这个(众多)中的一个例子是,为了确定用户是否在一组人中,我们必须尝试获取该组并解释所得到的“无组”异常。此外,所有这些例外都是一种类型。
我们正在使用C ++ 11开发一个庞大而复杂的项目,这个项目是多线程的,而且我们正在研究的领域涉及网络通信,因此我们必须同时调试多个实例。
我们的问题,以及我的问题的基础,是因为非例外情况对我们工作流程的影响。我们不愿意为API抛出的单一异常类型关闭第一次机会异常报告,因为这意味着如果我们调用了编码器错过了try / catch块的API,我们将放松主要和松散呼叫的上下文。如果我们将异常留下来,那么简单的非异常行为(例如上面示例中描述的行为)可能导致多次中断(初始抛出和可能的一些重新抛出),并且我们只能验证这实际上是非异常异常通过查询堆栈(通常是非主线程)来查找导致异常的API调用。
我相信我们的用例并不是那么独特,以至于其他人不会遇到相同的工作流问题,所以我的问题是我们应该如何改变我们的调试过程,以便更好地应对非例外异常所带来的问题,如上所述。
我们目前仅限于使用Visual Studio(或可能是WinDbg)进行调试。
答案 0 :(得分:1)
在非特殊用例中抛出异常是完全错误的。下一步:每个函数都是void
,抛出异常会返回所有函数。
据我所知,您正在使用第三方API来显示这种奇怪的行为。这是我在处理任何类型的“Odd API”时通常会考虑的内容,包括使用愚蠢的宏污染所有内容的C-API(是的,我看着你,WinAPI):
if(hasGroup) getGroup; else ...
而不是try {getGroup;} catch(X) {...}
不要让奇怪的东西扼杀所有代码,而是通过编写包装器API来约束它。在您的情况下:编写一个捕获异常的包装器并将其转换为正常的返回值。这样你的程序员就不会忘记捕获正常情况异常(因为你的包装器不会抛出它们),如果你把包装器放在它自己的库中,你可能可以在包装器API中使用另一个异常策略。 getGroup问题的快速示例:
//myAPIWrapper.h
namespace myAPIWrapper {
class Group;
class User {
public:
boost::optional<Group> getGroup();
};
}
//myAPIWrapper.cpp
#include "OddAPI.h"
namespace myAPIWrapper {
boost::optional<Group> User::getGroup()
{
boost::optional<Group> theGroup;
try {
oddAPI::user& oddUser= unwrap(*this);
oddAPI::group& oddGroup = oddUser.get_group();
theGroup = wrap(oddGroup);
}
catch(oddAPI::exception&) {
}
return theGroup;
}
}