assert用在那些你知道绝对不会发生的事情上,但是因为人总是会犯错误,保不准你写出来的东西跟你想的不一样。所以assert用来捕捉的是程序员自己的错误。
同理,exception捕捉的是用户或者环境的错误。
链接:https://www.zhihu.com/question/24461924/answer/27928436
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
关于异常和断言,个人以为,阐述最清楚的当属“契约式编程”。简而言之,检查前条件使用ASSERT,检查后条件使用异常。
以一个函数为例,它要求在开始执行的时候满足一系列条件,这些条件被称为“前条件”或者“先验条件”,比如,参数不为空,某全局变量应该为1,等等。不满足前条件,是不能调用此函数的,如果出现了前条件不满足仍然调用了此函数,可以认为这是一个设计错误。
检查前条件,可以使用ASSERT。
这个函数执行以后,也会满足一系列条件,这些条件被称为“后条件”或者“后验条件”,比如返回值满足什么关系,某全局变量设置称为什么什么,等等。这应该是函数执行的结果,在前条件满足的情况下,后条件如果没有满足是一种不正常的情况,那么使用异常来处理。
比如函数strcpy,它的前条件是 1、 第一个参数是一个NULL结尾的字符串;2、第二个参数所指向的内存空间足够用来复制。那么我们可以用ASSERT来检查是否满足这两个条件。它的后条件应该是 1、第二个参数所指向的内存空间中的字符串和第一个参数里面的是一样的。在函数执行完毕以后,我们可以检查一下是否一样,如果不一样,可以抛异常(比如当时这个空间正好被另外一个线程写入了一些东西导致异常,或者由于系统原因这块内存同时也分给了别人等等)。
当然实际上strcpy处于效率考虑没有做这些检查。
契约式编程中前条件不满足是程序错误,需要修改,这也与一般理解中出现ASSERT是程序错误符合;后条件不满足往往也是一些意外原因,也和一般理解中出现异常是意外情况符合。但是契约式编程还有一个问题是“不变式”,不变式指在函数执行之前和之后都不发生变化,我理解,在函数执行以前可以用ASSERT对不变式进行检查,在执行以后如果发现不变式发生了变化,那么应该抛出异常。
对于契约式编程我也没有系统的研究过,只是以前也遇到这个问题的时候,就事论事的学习了一下,欢迎拍砖。
见: 契约式设计Design by contract怎样解释 Design by Contract (契约式设计)?断言表示程序写错了,只要发生断言(更正:此处应为断言失败),意味着至少有一个人得修改代码。它的性质如同编译错误。
例如一个函数规定某输入参数非空,来个断言。如果调用者送了空参数触发断言失败,要么调用方改代码不传空参数,要么被调用方改代码允许空参数处理。
如果代码书写完全正确,但因外界环境或者用户操作仍然可能发生的事件,都不适合用断言,可以使用异常,或者条件判断处理。
至于异常,对不同语言来说含义不同。不可一概而论。作者:pansz
链接:https://www.zhihu.com/question/24461924/answer/27875536
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
assert处理的是 开发期 错误,在release代码上,assert是会移除的,所以,assert用来检查 程序员的错误。
如果你的程序模块化做得好,用assert可以保证所有错误不出模块,遇到错误就被拦截。
应用场景举例:- 检查参数有效性
- 检查数组越界
- switch/if控制流中的can't reach here放一个
- 不要free空指针
但是呢。。。也不是说每个数组都要检查越界,不是每个参数都要来一条assert。。。关键是要平衡,在重要代码处放上几个就可以了。
那么,什么是重要代码?怎样是达到平衡?。。。如果你不明白这个,说明你需要更多练习。你可以从给所有自己写错的代码加上assert开始。。。。。
异常是语言层面的机制,每个语言都不一样啊。。。
有的语言的异常就不是拿来用的,有的语言则鼓励你放个屁都要试一试
程序的运行期错误,比如网络程序网线被狗啃断了、写文件发现硬盘满了、权限不够。。。。。。。。
错误发生了必须被侦测到,然后必须处理,普通错误可以用检测函数返回值等方式捕捉,处理错误你可以写log、给提示、崩溃等等等等。 某些奇葩的错误检测、处理用异常 可能 会更好
所以,我对异常使用的建议是:尽量不使用。。。
作者:萧井陌
链接:https://www.zhihu.com/question/24461924/answer/27900433
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。