- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在 C++ 中,RAII 通常被认为是处理异常的一种优越方法:如果抛出异常,则解除堆栈,调用所有析构函数并清理资源。
但是,这会导致错误报告出现问题。假设一个非常通用的函数失败,堆栈被展开到顶层,我在日志中看到的只是:
Couldn't read from socket: connection reset by peer.
...或任何同样通用的消息。这并没有说明引发异常的上下文。特别是如果我正在运行类似事件队列处理循环的东西。
当然,我可以用 try/catch block 包装对套接字读取的每个调用,捕获异常,用更详细的上下文信息构造一个新的异常并重新抛出它,但这违背了拥有 RAII 的目的,并且是缓慢但肯定会比处理返回错误代码更糟糕。
在标准 C++ 中详细报告错误的更好方法是什么?我也愿意接受涉及 Boost 的建议。
最佳答案
正如 James McNellis 在这里所建议的,有一个非常巧妙的技巧,涉及到一个保护对象和 std::uncaught_exception
工具。
想法是这样写代码:
void function(int a, int b)
{
STACK_TRACE("function") << "a: " << a << ", b: " << b;
// do anything
}
并且仅在实际抛出异常的情况下记录消息。
类很简单:
class StackTrace: boost::noncopyable // doesn't make sense to copy it
{
public:
StackTrace(): mStream() {}
~StackTrace()
{
if (std::uncaught_exception())
{
std::cout << mStream.str() << '\n';
}
}
std::ostream& set(char const* function, char const* file, unsigned int line)
{
return mStream << file << "#" << line << " - " << function << " - ";
}
private:
std::ostringstream mStream;
};
#define STACK_TRACE(func) \
StackTrace ReallyUnwieldyName; \
ReallyUnwieldyName.set(func, __FILE__, __LINE__)
可以使用 __PRETTY_FUNC__
或等效项来避免命名函数,但我在实践中发现它对我自己的口味来说过于困惑/冗长。
请注意,如果您希望它一直存在到作用域的末尾,则需要一个命名对象,这就是这里的目的。我们可以想出一些棘手的方法来生成唯一标识符,但我从来不需要它,即使在函数内保护更窄的范围时,名称隐藏规则也对我们有利。
如果您将它与 ExceptionManager
(引发的异常自行注册的地方)结合使用,那么您可以获得对最新异常的引用,并且在进行日志记录时,您可以决定在其中设置堆栈异常本身。这样它就会被 what
打印出来,如果异常被丢弃则被忽略。
这是一个品味问题。
请注意,在存在 ExceptionManager
的情况下,您必须注意并非所有异常都可以用它检索 --> 只有您自己制作的异常。因此,您仍然需要采取措施防止 std::out_of_range
和第 3 方异常。
关于C++ 异常处理和错误报告习惯用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3783370/
我编写的代码主要供个人使用,但我正在考虑发布我最初开发供个人使用的应用程序(科学模拟/可视化)。 我的一个习惯是在类中使用一个main方法来单独测试类的运行情况。我认为这在某种程度上可能是不好的(毫无
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How do I convince programmers in my team to do TDD? 在从
假设我想测试是否有一个名为“Z”的驱动器。第一步是这样的; Get-PSProvider | Select-Object -Property Drives 这个给我; Drives: ... {C,
这是对 an old answer to a question about the necessity of functools.partial 的一种跟进: 虽然这个答案非常清楚地解释了这种现象及其
Perl 习惯很难改掉。两种语言之间的变量声明、作用域、全局/局部是不同的。是否有一组推荐的 python 语言习语可以使从 perl 编码到 python 编码的过渡不那么痛苦。 细微的变量拼写错误
我是一名优秀的程序员,十分优秀!