err.Raise 的问题

Bluess 2003-12-09 04:33:04
我在一个 dll 里写 err.Raise ,没有问题。当我把这个 dll 编译好,用另一个程序调用,就不会有 错误抛出,但是打开 dll 的源代码,就可以。为什么阿?在线等/
...全文
85 点赞 收藏 11
写回复
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
sogno 2003-12-10
vb的运行时刻错误处理机制的缺点是:
1、在错误处理不完善的情况下是危险的——如果没有完全捕获运行时刻错误,应用程序会立即退出,这可能导致用户的工作成果的丢失。这对系统的设计和测试提出了更高的要求。但是另外一方面,采用返回值的方式来处理错误的系统如果也有错误处理不完善的情况,虽然系统不会意外中止,但是在系统出错之后,系统内部已经无法保持正常的状态,很可能就会发生预期之外的行为,造成数据的丢失,甚至是严重的安全漏洞,而用户却浑然不觉。

2、与C++/java/.net系列语言的异常错误处理机制相比,vb的运行时刻错误处理机制过于简单了——它抛出的是错误号而不是异常对象,使得vb的异常无法类型化,失去了诸如编译时刻检查、只捕获特定类型异常/错误(从而进一步简化调用方异常处理代码)等等的好处。我觉得这可能由vb语言的特性决定的。vb不是一门真正的oo的语言,它既不支持实现继承,也不支持完全的接口继承,我想这是vb的设计人员没有采用对象化的异常处理机制的原因吧。
回复
sogno 2003-12-10
下面换成运行时错误机制来处理相同的问题:
sub3(原来的func3)由于不知道如何处理遇到的错误,就干脆不处理,只做它的事
代码如下:

'我是以前的func3
Public Sub sub3()
On Error GoTo Err
Call DoSomeThing '这里可能会发生运行时刻错误
End Sub

sub2(原来的func2)调用sub3,它知道停电了该怎么处理,其他的它不清楚,就原样送到调用方那边好了
代码如下:

'我是以前的func2
Public Sub sub2()
On Error GoTo Err

Call sub3
Call GoOnDoingTheRest '这里可能会发生运行时刻错误

Exit Sub
Err:
Dim errorNumber As Long
errorNumber = Err.Number
On Error GoTo 0
If errorNumber = LowPower Then
SwitchToUPS '不会出错
Else
Err.Raise errorNumber
End If
End Sub

sub1(原来的func1)代码:

'我是以前的sub1
Public Sub sub1()
On Error GoTo Err

Call sub2
CompleteTheMission '这里可能会发生运行时刻错误

Exit Sub
Err:
Dim errorNumber As Long
errorNumber = Err.Number
On Error GoTo 0
Select Case errorNumber
Case InsufficientMemory
BuyNewDisk "120G" '不会出错
ChangeDisk "120G" '不会出错
Case WriteDiskError
BuyMemory "512M" '不会出错
AppendMemory "512M" '不会出错
Case Else
MsgBox "搞不定了,您老看着办吧"
End Select
End Sub

我们看到,上面的sub1、sub2、sub3的业务代码和错误处理逻辑是界限分明的,无论是业务流程发生了变化,还是需要处理新的错误,修改起来都不困难,也就降低了代码维护的成本。
回复
sogno 2003-12-10
to Bluess(布鲁斯) :
在vb中使用错误返回机制,首先就是要捕获所有可能发生的错误,并一一转换为相应的返回值

举个简单的例子吧
有3个函数func1、func2、func3,其中func1调用func2,func2调用func3,它们共同完成一项任务

func3位于调用序列的最底层的,它捕获所有的运行时刻错误。但是由于它没有足够的信息来处理这些错误,就把错误转换为相应的返回值:
Public Function func3() As Long
On Error GoTo Err

Call DoSomeThing '这里可能会发生运行时刻错误

func3 = 0 '成功退出
Exit Function
Err:
Select Case Err.Number
Case InsufficientMemory
func3 = -1 '出错
Case WriteDiskError
func3 = -2 '出错
Case LowPower
func3 = -3 '又出错
End Select
On Error GoTo 0
End Function

func2接受func3的返回值,并且能够处理其中一部分错误,剩下的错误它没有办法解决,就返回给它的调用方,另外它也无法处理所有它捕获到的运行时刻错误,也转换为返回值一并返回
Public Function func2() As Long
Dim result As Long
result = func3
If 0 = result Then
On Error GoTo Err
Call GoOnDoingTheRest '这里可能会发生运行时刻错误
func2 = 0
ElseIf -3 = result Then
Call SwitchToUPS '不会出错
Else
func2 = result
End If
Exit Function
Err:
func2 = -4
On Error GoTo 0
End Function

func1是调用序列中的最后一个,它要处理掉前面处理不了的错误,同样的,它也要捕获所有的运行时刻错误。它罩不住的时候,就丢给用户
Public Sub sub1()
Dim result As Long
result = func2
If 0 = result Then
On Error GoTo Err
CompleteTheMission '这里可能会发生运行时刻错误
ElseIf -2 = result Then
BuyNewDisk "120G" '不会出错
ChangeDisk "120G" '不会出错
ElseIf -1 = result Then
BuyMemory "512M" '不会出错
AppendMemory "512M" '不会出错
Else
MsgBox "搞不定了,您老看着办吧"
End If
Exit Sub
Err:
On Error GoTo 0
MsgBox "搞不定了,您老看着办吧"
End Sub

对于计算机来说,这些代码是完美的,它指出了通向圆满完成任务的成功之路,可是对于需要维护这段程序的人来说,事情就不是那么美好了。首先,整齐的、具有正确缩进的if-else语句抹煞了正常控制流和异常控制流的区别,业务逻辑、出错处理都掺杂在一起。当然,对于这个简单的例子来说,以绝大大部分程序员的理解能力来说都不成问题,但如果流程再复杂一些,比如具有多种正常状态的返回值,还有需要捕获更多的错误等等,那时想要加入一个新的正常/异常分支就困难了
回复
Bluess 2003-12-09
我的程序好了. 我把 dll  里的  On Err GoTo Handler  去掉,就好了
回复
Bluess 2003-12-09
to sogno : 能说说 运行时错误机制 与 错误返回值机制 吗?
回复
sogno 2003-12-09
一种可能性是:你的VB IDE中的tools->option->ErrTrapping设置成了Break on All Errors,而你在dll里捕获了这个错误,这样在调试时错误就会抛出,而运行时没有。

另外一种可能性是你的dll客户代码的输入参数没有覆盖到抛出错误的代码。

有可能的话还是把代码贴出来吧

另外,我认为用运行时错误机制优于错误返回值机制,它可以简化调用方代码、分离正常/异常的控制流,更明晰得体现出代码的责任
回复
online 2003-12-09
在dll中一般把错误返回,不需要在内部产生错误
回复
up

学习
回复
AresChen 2003-12-09
不过我一般也不推荐在dll中使用err来产生错误,最好是模仿API的形式,一般的函数全部都返回一个Long型的值来代表是否出错,在设置一个属性LastError来返回最后一次的错误信息。
回复
AresChen 2003-12-09
检查一下是不是调用方的dll中使用on error的错误处理。
回复
davidlv 2003-12-09
不要在DLL中这样写,会有问题的,因为错误是出现在DLL中的,它无法返回到调用它的过程中。你在DLL中写一个东西如
public function a as string
a=err.description
end function

你通过得到A的内容,就可以得到错误信息了,我就是这样处理的。
回复
发动态
发帖子
VB基础类
创建于2007-09-28

7449

社区成员

VB 基础类
申请成为版主
社区公告
暂无公告