比C++中的异常处理更好的语言功能?

Kla*_*aim 5 c++ language-agnostic programming-languages exception-handling exception

(不确定它是否只是一个C++的东西)

异常处理在C++中很难学习,当然不是一个完美的解决方案,但在大多数情况下(除了一些特定的嵌入式软件环境),它肯定是我们目前用于异常处理的更好的解决方案.

未来怎么样?

是否有其他已知的方法来处理大多数语言中未实现的错误,或者只是大学研究?

换句话说:是否(通常)已知更好(不完美可行)的方法来处理编程语言中的错误?

Ken*_*oom 10

嗯,总有返回代码errno等.一般的问题是那些不知道特定呼叫可能失败的程序员可以忽略或忘记这些.程序员也经常忽略或错过例外情况.不同之处在于,如果您没有捕获异常,程序就会死亡.如果不检查返回代码,程序将继续对无效数据进行操作.Java试图通过创建已检查的异常来强制程序员捕获所有异常,如果您没有准确指定它们何时可以传播并最终捕获它们,则会导致编译错误.事实证明这非常令人讨厌,所以程序员catch(...){/* do nothing*/}尽可能地接近(尽可能接近C++ parlence)的例外情况,

除了这两种错误技术之外,一些函数语言还支持使用各种monadic返回类型,这些类型可以封装错误和返回值(例如Scala的Either类型,Option类型或monad,它允许您返回一个近似答案以及失败日志).这些优点是,使用成功返回值的唯一方法是在monad中执行代码,monad确保在发生故障时不运行代码.(对于那些不是Haskell或Scala程序员的人来说,解释起来相当复杂.)我没有那么多地使用过这个模型,但我认为对于某些人来说,这会像检查异常一样烦人.

基本上,IMO,错误检查是一种态度问题.你有三个选择:

  1. 意识到你必须处理它,愉快地接受这个事实,并努力编写正确的错误处理代码.(任何一位)
  2. 使用迫使您处理它的语言功能,并因为您不想处理它而烦恼,特别是当您确定错误永远不会发生时.(已检查的例外情况,Monads)
  3. 使用langauge功能可以轻松忽略它,并编写不安全的代码,因为你忽略了它.(未经检查的例外,返回代码)
  4. 通过使用强制您处理它的语言功能来获取选项2和3中最差的选项,但是以明确忽略它的方式处理每个错误.(已检查的例外情况,Monads)

显然,你应该尝试成为#1类型的程序员.


Ste*_*sop 6

假设您希望代码根据是否发生错误而执行不同的操作,您基本上有三个选项:

1)在代码中的任何地方显示它(C样式错误返回值检查).主要的缺点是它很冗长.

2)使用非本地控制流将错误处理代码与"通常路径"(例外)分开.主要的缺点是跟踪代码可以接下来的所有位置,特别是如果记录的接口并不总是列出所有这些.Java的实验以及"处理"后一个问题的检查异常也未完全成功.

3)坐在错误上直到"以后"(IEEE风格的粘滞错误位和安静的NaN,流上的C++错误标志),并且仅在方便调用者时检查它们.主要的缺点是设置和清除错误需要每个人小心使用,并且错误站点上可用的信息可能在处理时丢失.

随便挑选.(1)看起来臃肿而复杂,并且新手通过不正确检查错误来搞乱它,但每行代码都很容易推理.(2)看起来小而简单,但是每一行代码都可能导致跳到谁知道哪里,所以新手通过不正确地实现异常保证来搞乱它,并且每个人有时会在错误的地方捕获异常或根本不捕获异常.(3)设计的时候很好,但你永远不知道有哪几种可能性的每一行代码实际上是很大的,所以在丰富UB环境,比如C++,很容易搞乱了.

我认为潜在的问题基本上很难:处理错误明确地增加了代码中的分支.在特定的代码中,处理错误会悄悄地增加您需要推理的状态量.

例外也有"它真的特别吗?" 问题.您可以通过仅在整个程序无法恢复的情况下抛出异常来防止异常导致混乱的控制流.但是你不能将它们用于可以从程序的POV中恢复的错误,而不能从子系统的POV中恢复,因此对于这些情况,你可以回到(1)或(3)的缺点.


Kri*_*son 5

我不能说它比异常更好,但另一种选择是Erlang开发人员实现容错的方式,称为"让它失败".总结一下:每个任务都是作为一个单独的"过程"产生的(Erlang的术语是大多数人所说的"线程").如果一个进程遇到错误,它就会死掉,并且通知会回到控制进程,这可以忽略它或采取某种纠正措施.

这可能会导致代码更简单,更健壮,因为整个程序不会因为缺少错误处理而崩溃或退出.(请注意,这种健壮性依赖于Erlang语言和运行时环境的一些其他功能.)

Joe Armstrong的论文包括一个关于他如何设想容错Erlang系统的论文,可以下载:http://www.erlang.org/download/armstrong_thesis_2003.pdf

  • 要明确的是,Erlang有这个理念的原因是当你产生一个新的过程时,它不会"返回"任何东西.您向其发送要处理的消息,并且*可能*发回消息作为响应. (3认同)
  • +1:实际上Erlangs的方法是"让它失败,无论如何我们都忽略它;>" (2认同)
  • @dsimcha,@ seand:关于Erlang的哲学的事情是,你不是*取决于结果,因此.通常,当你产生一个进程时,它会处理一些工作,你真的不关心它是否成功完成.Erlang是为PBX等容错系统设计的,如果出现问题,你宁可不会传播到正在运行的进程.同样,如果您正在运行Web服务,则不希望在一个会话中出现一个错误,从而导致整个系统崩溃.你只需让这个过程死掉并重新开始. (2认同)