异常与errno
作为一名C程序员,我对异常没有太多经验。我习惯于将errno
作为跨多个函数调用进行通信错误的方式。这就是说,我没有看到例外的显着特征,所以...异常与errno
例外和使用errno
之间的根本区别是什么?
这里有这么多的差异,很难说从哪里开始。
首先,在C中使用的errno
是一个全局变量;这意味着每个调用errno
的子程序在执行任何其他工作前必须检查errno
,如果它关心正确性的话。幸运的是,errno is threadsafe。
C++异常会自动解除调用堆栈,直到找到准备处理故障的函数。这意味着在大多数情况下,用户不必显式检查每个呼叫的错误;相反,他们可以在一个地方收集错误回报。与errno不同,C++异常可以包含整数以外的值。
1)异常可以是任何东西,不只是一个整数。所以传递的数据是不同的。
2)异常做非本地控制流程,所以你不必在每个级别检查在实践中与errno
的方式,你也返回一个值,指示错误,每个调用者检查错误和保释如果已经发生,就提前退出。相反,错误返回会执行本地控制流程,因此您始终可以准确查看错误何时通过给定的代码传播。这种差异从根本上改变了编码风格。所以沟通方式也不同。
对我来说,最重要的区别是errno
很容易被忽略,而异常很难忽略 - 如果最终忽略它们,程序将终止......另外,异常是(好的,应该是)对象,所以你可以携带更多有用的信息。
另一个非常重要的区别是,在软件可以真正做出明智决定如何处理问题时,可以轻松地处理异常,通常是调用堆栈的几个层次。这对于错误代码来说并不容易。
你可以随便忽略errno。必须处理例外情况。
当然,我已经看到了我的份额:
try {
// something
}
catch(...) {
// nothing
}
// continue as if nothing happened
和(Java)的
try {
// something
}
catch(Throwable t) {
// nothing
}
// continue as if nothing happened
但至少你这有点儿跳了出来,当你通过别人的烂摊子春耕。
我发现在嵌入式系统上有用的一种模式是为每个流设置一个错误标志,但规定当标志设置时尝试的I/O操作将立即失败。因此,代码可以这样做:
pkt_type = tcp_getbyte(my_stream, timeout); pkt_length = tcp_getbyte(my_stream, timeout); pkt_length |= tcp_getbyte(my_stream, timeout) << 8; if (pkt_length < MAX_PACKET_LENGTH) { for (i=0; i<pkt_length; i++) buffer[i] = tcp_getbyte(my_stream, timeout); } if (!my_stream->error) { /* Do something with packet */ }
如果一个试图得到一个字节超时,随后试图将无条件失败,返回零。没有必要检查每个操作的失败;如果出现问题,系统最终会像tcp_getbyte()抛出异常一样运行,只是速度不够快。
非常简单:它是完全有效的,可以忽略异常。它具有出色的定义行为。 – 2011-05-13 01:33:48