为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?

时间:2022-11-19 23:54:44
为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?
以下是msdn的原文,
On Error Resume Next 说明当一个运行时错误发生时,控件转到紧接着发生错误的语句之后的语句,并在此继续运行。访问对象时要使用这种形式而不使用 On Error GoTo。 


我不明白为什么这样说,访问对象为何就要忽略错误呢,不能用 on error goto 呢?

44 个解决方案

#1


不能一概而论,究竟是用on error resume next 还是 on error goto,要视情况而定,一般而言,我比较喜欢用on error resume next,因为它不会因为程序错误而当掉,当调试程序想发现错误提示信息时,需要将on error resume next 暂时改为 on error goto

#2


你从哪里看来的这句话??

#3


尽量不用resume next,尽量将错误从根部拔掉。一再的将错误放行,将会导致未来的扩展和维护代价升高。

#4


Resume:恢复,并重新开始。
goto:   跳转。
使用Resume语句时,系统将清空系统错误Err对象(Err对象是个隐藏的全局变量),并重新执行程序。而goto只是跳转执行而保留错误记录,当重新产生错误时,系统就无法再次进行跳转(也无法进行恢复)
如果使用对象,可以使用on error resume next后,接着根据err.number来进行错误处理。如果想实现goto的功能,可以使用 resume Lablename 语句

#5


分三种情况:
1、有些错误需要程序处理,就用on error goto 
2、有些错误不需要处理,就用on error resume next,例如:有一个窗体内控件需要随着窗体大小的改变而改变,但是在窗体变得太小,或者最小化时,设置控件大小的语句就可能发生错误,这时就需要忽略掉错误继续执行后面的语句,on error resume next就非常适合。
3、在发生错误以后需要错误处理,但是还要继续执行后面的语句,这时也要用on error resume next语句,不过在可能发生错误的语句之后需要检查有无错误发生,并接着进行相应的处理。

#6


引用 2 楼 wallescai 的回复:
你从哪里看来的这句话??


msdn呀,就是vb6自带的帮助.

#7


2、有些错误不需要处理,就用on error resume next,例如:有一个窗体内控件需要随着窗体大小的改变而改变,但是在窗体变得太小,或者最小化时,设置控件大小的语句就可能发生错误,这时就需要忽略掉错误继续执行后面的语句,on error resume next就非常适合。
--------------------------------------------------------------------------
这本身就是需要你控制窗体最小大小的问题,而不是将错就错:)


楼主的既然看了你引用的那段,那也应该看到这一段了。

每次和对象打交道,在不知道用代码访问哪个对象时,检查一下 Err 都会打消这种疑虑。可以确定是哪个对象产生错误(Err.Source 中指定的对象),也可以确定是哪个对象将错误代码放在 Err.Number 中。

#8


学习

#9


这本身就是需要你控制窗体最小大小的问题,而不是将错就错
--------------------------------------------------
你遇到过这样的问题吗,只有你遇到过(例如在resize事件中),并且用解决它,你才知道on error resume next这一句的妙处,什么事情都不能走极端的,有那样绝对的事吗?那干嘛微软干嘛还保留这一句呢?

#10


引用 9 楼 li_yaoming 的回复:
这本身就是需要你控制窗体最小大小的问题,而不是将错就错
--------------------------------------------------
你遇到过这样的问题吗,只有你遇到过(例如在resize事件中),并且用解决它,你才知道on error resume next这一句的妙处,什么事情都不能走极端的,有那样绝对的事吗?那干嘛微软干嘛还保留这一句呢?

你遇到过这样的问题吗,只有你遇到过(例如在resize事件中),并且用解决它,你才知道on error resume next这一句的妙处
在窗体事件resize用resume next是个很妙的主意?我还是第一次听说,按窗体大小修改控件大小并不代表窗体只有宽度1时,你还要缩放你的控件宽度到0.1,这个控件不能缩到0.1,你就去缩放下一个?难道你要告诉我这个很妙?
什么事情都不能走极端的,有那样绝对的事吗
我从未说过必须,所以不绝对。
那干嘛微软干嘛还保留这一句呢?
这不是我所能解释的,我不是微软。这句代码是有些好处,我也从未全盘否定。


PS:
对事不对人,我说尽量不用resume next也只是提醒楼主少用这个语句。

#11


你在MSDN里哪个章节看到的?这段话显然是在一定的语境下说的。把你看的这篇文章的标题列出来,这样大家才好帮你解释。

另外,你在MSDN的界面里点一下“定位”那个按钮,就可以看到你现在在看的章节是属于哪本书。

#12


On Error 语句
      

启动一个错误处理程序并指定该子程序在一个过程中的位置;也可用来禁止一个错误处理程序。

语法

On Error GoTo line 

On Error Resume Next

On Error GoTo 0

On Error 语句的语法可以具有以下任何一种形式:

语句 描述 
On Error GoTo line  启动错误处理程序,且该例程从必要的 line 参数中指定的 line 开始。line 参数可以是任何行标签或行号。如果发生一个运行时错误,则控件会跳到 line,激活错误处理程序。指定的 line 必须在一个过程中,这个过程与 On Error 语句相同; 否则会发生编译时间错误。 
On Error Resume Next 说明当一个运行时错误发生时,控件转到紧接着发生错误的语句之后的语句,并在此继续运行。访问对象时要使用这种形式而不使用 On Error GoTo。 
On Error GoTo 0 禁止当前过程中任何已启动的错误处理程序。 


说明

如果不使用 On Error 语句,则任何运行时错误都是致命的;也就是说,结果会导致显示错误信息并中止运行。

一个“允许的”错误处理程序是由 On Error 语句打开的一个处理程序;一个“活动的”错误处理程序是处理错误的过程中允许的错误处理程序。如果在错误处理程序处于活动状态时(在发生错误和执行 Resume、Exit Sub、Exit Function 或 Exit Property 语句之间这段时间)又发生错误,则当前过程的错误处理程序将无法处理这个错误。控件返回调用的过程。如果调用过程有一个已启动的错误处理程序,则激活错误处理程序来处理该错误。如果调用过程的错误处理程序也是活动的,则控件将再往回传到前面的调用过程,这样一直进行下去,直到找到一个被允许的但不是活动的错误处理程序为止。如果没有找到被允许而且不活动的错误处理程序,那么在错误实际发生的地方,错误本身是严重的。错误处理程序每次将控件返回调用过程时,该过程就成为当前过程。在任何过程中,一旦错误处理程序处理了错误,在当前过程中就会从 Resume 语句指定的位置恢复运行。

注意 一个错误处理程序不是 Sub 过程或 Function 过程。它是一段用行标签或行号标记的代码。

错误处理程序依靠 Err 对象的 Number 属性中的值来确定错误发生的原因。在其它任何错误发生之前,或在调用一个可能会导致错误发生的过程之前,错误处理程序应该先测试或存储 Err 对象中相关的属性值。Err 对象中的属性值只反映最近发生的错误。Err.Description 中包含有与 Err.Number 相关联的错误信息。

On Error Resume Next 会使程序从紧随产生错误的语句之后的语句继续执行,或是从紧随最近一次调用含有 On Error Resume Next 语句的过程的语句继续运行。这个语句可以置运行时错误于不顾,使程序得以继续执行。可以将错误处理程序放置在错误发生的地方,而不必将控件传输到过程中的其它位置。在调用另一个过程时,On Error Resume Next 语句成为非活动的,所以,如果希望在例程中进行嵌入错误处理,则应在每一个调用的例程中执行 On Error Resume Next 语句。

注意 当处理在访问其它对象期间产生的错误时,与其使用 On Error GoTo 指令,不如使用 On Error Resume Next。每次和对象打交道,在不知道用代码访问哪个对象时,检查一下 Err 都会打消这种疑虑。可以确定是哪个对象产生错误(Err.Source 中指定的对象),也可以确定是哪个对象将错误代码放在 Err.Number 中。

On Error GoTo 0 停止在当前过程中处理错误。即使过程中包含编号为 0 的行,它也不把行 0 指定为处理错误的代码的起点。如果没有 On Error GoTo 0 语句,在退出过程时,错误处理程序会自动关闭。

在错误未发生的时候,为了防止错误处理程序代码运行,请像在下段程序中那样,在紧靠着错误处理程序的前面写入 Exit Sub、Exit Function 或 Exit Property 语句。

Sub InitializeMatrix(Var1, Var2, Var3, Var4)
   On Error GoTo ErrorHandler
   . . .
   Exit Sub
ErrorHandler:
   . . .
   Resume Next
End Sub

此处,错误处理程序代码在 Exit Sub 语句之后,而在 End Sub 语句之前,从而与过程中的流程分开。错误处理程序代码可以在程序中的任何地方写入。

当对象作为文件运行时,对象中未捕获的错误都被返回控制应用程序。在开发环境中,如果设置了正确选项,未捕获的错误只返回控制应用程序。请参考主应用程序的文档的有关描述,从而得知,在调试时应该设置哪些选项、如何设置这些选项以及主机能否建立类。

如果建立一个访问其它对象的对象,则应该着手处理从那些对象返回的未处理错误。如果无法处理这种错误,请将 Err.Number 中的错误代码当作自己的一个错误,然后将错误回传给对象的调用者。应该将错误代码添加到 vbObjectError 常数上来指定这个错误。举例来说,如果错误代码为 1052,则使用如下方法指定错误:

Err.Number = vbObjectError + 1052

注意 调用动态链接库 (DLL) 期间产生的系统错误不会产生例外情况,也不会被 Visual Basic 的错误捕获操作所捕获。当调用 DLL 函数时,应该(根据 API 的详细说明)检查每一个返回值以确定是成功还是失败,如果失败,则检查 Err 对象的 LastDLLError 属性中的值。

#13


Private Sub pic_left_Resize()
On Error Resume Next
    dg_result.Height = pic_left.Height - 400
    dg_result.Width = pic_left.Width - 60
End Sub
这是我程序中的一个resize事件,在改变窗口大小,pic_left.Height - 400小于零时,就会发生异常,产生错误,在程序中是没有必要处理这样的错误的,所以用On Error Resume Next,我想,大家遇到这样的问题也会采用一样的方式的。
次之,vc中有try--catch语句,vb中有了On Error Resume Next才能得到相同的效果。
注意:我也是对事不对人的,大家互相学习讨论,谁对谁错没有那么重要,不要误解。

#14


引用 13 楼 li_yaoming 的回复:
...

不多说了,偏离了楼主主题太远了 :)

#15


看来是是在看《参考手册》里On Error语句的内容。

我的MSDN是英文版的,给你找到了对应的英文句子。


访问对象时要使用这种形式而不使用 On Error GoTo。
Use this form  rather than On Error GoTo when accessing objects.


当处理在访问其它对象期间产生的错误时, 与其使用 On Error GoTo 指令, 不如使用 On Error Resume Next。
The On Error Resume Next construct may be  preferable to On Error GoTo when handling errors generated during access to other objects. 

从这两段话的英文原文来看,MSDN是在给出 建议,而不是硬性规定。

#16


但是为何要给出这样的建议,我好像也没看懂,和楼主一起等其他朋友来指点。

下面是MSDN给出的例子,我在想,在用On Error Resume Next的地方用On Error GoTo ErrorHandler也没什么不好啊?

Sub OnErrorStatementDemo()
   On Error GoTo ErrorHandler   ' Enable error-handling routine.
   Open "TESTFILE" For Output As #1   ' Open file for output.
   Kill "TESTFILE"   ' Attempt to delete open 
            ' file.
   On Error Goto 0   ' Turn off error trapping.
   On Error Resume Next   ' Defer error trapping.
   ObjectRef = GetObject("MyWord.Basic")   ' Try to start nonexistent
            ' object, then test for 
'Check for likely Automation errors.
   If Err.Number = 440 Or Err.Number = 432 Then
      ' Tell user what happened. Then clear the Err object.
      Msg = "There was an error attempting to open the Automation object!"
      MsgBox Msg, , "Deferred Error Test"
      Err.Clear   ' Clear Err object fields 
   End If   
Exit Sub      ' Exit to avoid handler.
ErrorHandler:   ' Error-handling routine.
   Select Case Err.Number   ' Evaluate error number.
      Case 55   ' "File already open" error.
         Close #1   ' Close open file.
      Case Else
         ' Handle other situations here... 
   End Select
   Resume   ' Resume execution at same line
            ' that caused the error.
End Sub


MSDN对上述例子的说明:This example first uses the On Error GoTo statement to specify the location of an error-handling routine within a procedure. In the example, an attempt to delete an open file generates error number 55. The error is handled in the error-handling routine, and control is then returned to the statement that caused the error. The On Error GoTo 0 statement turns off error trapping. Then the On Error Resume Next statement is used to defer error trapping so that the context for the error generated by the next statement can be known for certain. Note that Err.Clear is used to clear the Err object's properties after the error is handled.

#17


AC和li_yaoming,你们可能还真没讨论到点儿上。MSDN的意思似乎并不是说用了On Error Resume Next之后就不处理错误了,而只是 Defer error trapping

至于为何在处理和访问对象相关的错误时defer比直接跳转好,MSDN却没有给出说明。

#18


这话的意思是 On Error Resume Next 可以在错误发生后马上处理。
比较下面两种方式(用 a、b、c 代替错误号)
Sub Main()
    On Error Resume Next

    Call Sub1
    If Err.Number <> 0 Then
        Select Case Err.Number
            Case a:     MsgBox "Sub1 发生 AAA 错误"
            Case b:     MsgBox "Sub1 发生 BBB 错误"
            Case Else:  MsgBox "Sub1 发生未知错误 " & Err.Number
        End Select
        Exit Sub
    End If

    Call Sub2
    If Err.Number <> 0 Then
        Select Case Err.Number
            Case a:     MsgBox "Sub1 发生 AAA 错误"
            Case c:     MsgBox "Sub2 发生 CCC 错误"
            Case Else:  MsgBox "Sub2 发生未知错误 " & Err.Number
        End Select
        Call cancel1
    End If
End Sub

Sub Main()
    On Error GoTo ErrHandler
    Dim iStep As Long
    Dim sStepName As String
    
    iStep = 1
    Call Sub1
    iStep = 2
    Call Sub2
    
ExitEntry:
    Exit Sub
ErrHandler:
    sStepName = Choose(iStep, "Sub1", "Sub2")
    Select Case Err.Number
        Case a:     MsgBox sStepName & " 发生 AAA 错误"
        Case b:     MsgBox sStepName & " 发生 BBB 错误"
        Case c:     MsgBox sStepName & " 发生 CCC 错误"
        Case Else:  MsgBox sStepName & " 发生未知错误 " & Err.Number
    End Select
    If iStep = 2 Then
        Call cancel1
    End If
    Resume ExitEntry
End Sub

#19


我猜测一个可能的原因是因为来自对象的错误编号也许会和其他的错误编号搞混,所以不把相关的错误处理放在ErrorHandler,而是放在紧随其后的代码里,像16楼的例子里那样。

从4楼的回复来看,坏上帝也很熟悉这种用法。

#20


Tiger_Zhao,你的理解正确,可是你也没说明为什么这样做更好?

#21


关键是类似错误发生后的 Cancel1() 调用,不同步骤有不同处理,步骤多的话顺序结构比较清晰。

#22


这跟 对象有什么关系?貌似没说到 点子上(再次模仿chenhui说,嘿嘿)

#23


我觉得对MSDN不必咬文嚼字,或许是翻译造成的歧意,错误处理那有什么定式.....一切都根据需要来处理
On Error Resume Next用于忽略错误或者嵌入错误处理的场合,一定要把那个objects之类的翻译为对象或者理解成VB中我们常规认识的对象那就钻牛角尖吧....不要说我误导,个人观点而已....

#24


引用 22 楼 slowgrace 的回复:
这跟对象有什么关系?貌似没说到点子上(再次模仿chenhui说,嘿嘿)

老鸟是写的错误处理范例,MSDN推荐使用resume next进行错误处理。

#25


如果你有以下需求:
1)不在乎程序中的出错,或者说你觉得你可以保证程序没有任何错误、甚至连语法错误也没有;
2)即使出错了你也不想让自己知道更不想让别人知道;
3)测试结果表明程序有问题也不想快速定位出错位置;
那么恭喜你:
你完全可以用“on error resume next”。

但是,
如果你是:
1)严格要求自己写出好程序;
2)想保证编译后不出简单错误,比如说简单的变量未定义错误,不愿意让客户或上级找到你所写程序的根本不应该出现的最简单错误;
3)如果出错的话,能快速定位出错位置,快速找到出错原因--即使最后表明是因为别人出了错;
那么很抱歉,
你最好:
1)尽量少用“on error resume next”,但也不排除在需要的时候技巧性地使用“on error resume next”--比如说在你可预知的错误出现前使用“on error resume next”;
2)在使用“on error goto xxx”的xxx处,有相应的错误信息输出到文件或终端,并且视客户要求在出错以后选择使用“resume next”或“Exit Sub”或“Exit Function”;

#26


引用楼主 kanzm 的回复:
为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?
以下是msdn的原文,
 On Error Resume Next 说明当一个运行时错误发生时,控件转到紧接着发生错误的语句之后的语句,并在此继续运行。访问对象时要使用这种形式而不使用 On Error GoTo。

 我不明白为什么这样说,访问对象为何就要忽略错误呢,不能用 on error goto 呢?


MSDN并不是神,
这方面它写得其实并不好的。

实际上,
乱用“on error resume next”的话很容易让人陷入歧途。
原因很简单,
“on error resume next”的意思就是:出错后什么也不管,继续执行下一句。

#27


调用者(Caller) 无论从中文还是英文都看起来像个对象,可是无对象的纯过程也可以叫做调用者。

技术文档不是字典,不能咬文嚼字。

#28


引用 15 楼 slowgrace 的回复:
看来是是在看《参考手册》里On Error语句的内容。

 我的MSDN是英文版的,给你找到了对应的英文句子。


 访问对象时要使用这种形式而不使用 On Error GoTo。
 Use this formrather thanOn Error GoTo when accessing objects.


 当处理在访问其它对象期间产生的错误时,与其使用 On Error GoTo 指令,不如使用 On Error Resume Next。
 The On Error Resume Next construct may bepreferableto On Error GoTo when handling errors generated during access to other objects.

 从这两段话的英文原文来看,MSDN是在给出建议,而不是硬性规定。

这都may be preferable了,就是个建议
我个人的理解,由于vb没有.net那种结构化错误处理。
on error resume next给了一个在后面代码中根据err.number作判断的机会,或者直接忽略进行以后的动作
on error goto ...也是一种错误处理方式,需要跳过中间一段代码
具体哪个时候用哪个实在太灵活了,而且也没有硬性规定哪个好
函数中可以出现

private sub Func()
 on error resume next 
 ....
 ....
 if err.number... then
 end if 
 on error goto errhandler
 ...

errhandler
end sub

#29


你的Caller从哪里冒出来的?你看我在15楼引用的原文。

我的 结论
On Error Resume Next实际上通常有两种用法:一种是用来忽略错误(比如13楼);一种是用来随后立即处理错误但却保持顺序的程序结构(比如18楼)。

我想,理解了通常在什么情况下用这两种用法也就可以了。至于MSDN这两段让人费解的话,也许我们暂且可以理解它是一个概念不清的文档写作者写的(比如像我这样的,呵呵),可以不必理会。

#30


29楼第一句回给赵老虎的。

#31


虽然经大家劝说,俺打算放弃这题了。不过的话,你们看看下面这段话,会不会和上面的话有点关联?

“Unhandled errors in event procedures will be fatal to your control component, and the application using it, because there will never be a procedure on the call stack that can handle the errors.”

这段话是针对ActiveX Control说的。

#32


MSDN里只是一种"技巧建议",并非"必须的语法"吧.

实际情况很复杂,不能一概而论.

#33


引用 29 楼 slowgrace 的回复:
你的Caller从哪里冒出来的?你看我在15楼引用的原文。

只是举例,我们平时的用词就经不起咬文嚼字。

#34


请教你这个: http://topic.csdn.net/u/20090730/09/0a31adcc-6948-4331-8042-067774134722.html?seed=1008754042&r=58901954#r_58901954

olb文件在VB里可以引用,也看到ACCESS的对象库了,但是在部件里却找不到它的踪影。(那边我不能回复了:)

#35


对象变量的使用,可能是多种形式,存在着使用后立刻释放的情况
在极端情况下对于对象的对象的引用,是动态引用的,vb的调用方式是,调用后立刻释放
如果此时转移代码,猜想,可能造成对象无法释放,原因是释放语句在调用语句之后

做个测试

class1:
property get GetUserObject(byval index as long)as class2
   if .. index 有效 set GetUserObject = xxxx
end 。。。

class2:
过程略,在类的初始化和退出过程加个 debug.print 可以清楚的看到效果


当用 on error goto 时,错误发生在对象内部,被调用函数截获,会立刻执行转移
这时释放 GetUserObject 所获取的对象本应在调用后立刻释放,但被转移了,释放过程被忽略了

如果用 on error resume nexe 就会同msdn所述,继续下一条语句,这条语句就应该是释放了

如果释放未执行,则对象引用计数是无法消减的,被引用的对象就可能会无法真正的退出。

只是个人意见,大家酌情参考。。。
我只是觉得,能做vb的人肯定也想到了各种各样的问题,而且自动编译器,不一定能智能到,自动掌握所有用户代码形式,有些非常*的代码形式,恐怕还得手动做。。。

#36


为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?
我的意思好像没有说清
大概意思就是,因为对象的特点,以及程序应追求的正确申请释放资源的原则来讲,对于 on error goto 和
on error resume next 应为有区别使用。
上面我回贴的内容仅仅是列举了一种,需要使用 on error resume next 来处理的情况,当然肯定还会有很多

#37


呵呵,好久没见了 为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?

这个解释疑似靠谱 为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?,待我试试。

#38


如果程序中使用了多个同一个类型的对象,它们的err.number,err.source等都是相同的,在errorhandler中难以区别是程序中具体哪一个对象引发的。而用on error resume next,就能解决这个问题。

#39


具体怎么用这个得具体问题具体分析,并不像楼主所理解的那样。
个人对这两个语句的理解:
1、On Error Resume Next :触发错误,忽略它,继续执行
2、On Error GoTo xxx:触发错误,跳转到指定的位置:xxx

#40


引用 37 楼 slowgrace 的回复:


为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?

#41


引用 39 楼 veron_04 的回复:
具体怎么用这个得具体问题具体分析,并不像楼主所理解的那样。
 个人对这两个语句的理解:
 1、On Error Resume Next :触发错误,忽略它,继续执行
 2、On Error GoTo xxx:触发错误,跳转到指定的位置:xxx

 1、On Error Resume Next :触发错误,忽略它,继续执行
================
在继续执行时,下面的语句可以就是错误处理语句。


On Error GoTo xxx:触发错误,跳转到指定的位置:xxx
================
理论上,只要愿意,在这里也不进行任何实质的错误处理。

#42


引用 35 楼 pctgl 的回复:
对象变量的使用,可能是多种形式,存在着使用后立刻释放的情况
在极端情况下对于对象的对象的引用,是动态引用的,vb的调用方式是,调用后立刻释放
如果此时转移代码,猜想,可能造成对象无法释放,原因是释放语句在调用语句之后

做个测试

class1:
property get GetUserObject(byval index as long)as class2
  if .. index 有效 set GetUserObject = xxxx
end 。。。

class2:
过程略,在类的初始化和退出过程加个 debug.print 可以清楚的看到效果


当用 on error goto 时,错误发生在对象内部,被调用函数截获,会立刻执行转移
这时释放 GetUserObject 所获取的对象本应在调用后立刻释放,但被转移了,释放过程被忽略了

如果用 on error resume nexe 就会同msdn所述,继续下一条语句,这条语句就应该是释放了

如果释放未执行,则对象引用计数是无法消减的,被引用的对象就可能会无法真正的退出。

只是个人意见,大家酌情参考。。。
我只是觉得,能做vb的人肯定也想到了各种各样的问题,而且自动编译器,不一定能智能到,自动掌握所有用户代码形式,有些非常*的代码形式,恐怕还得手动做。。。



Class1:
Option Explicit

Public Sub test()
    Err.Raise 1
End Sub

Private Sub Class_Terminate()
    Debug.Print "free"
End Sub


Class2:
Option Explicit

Property Get test() As Class1
    Set test = New Class1
End Property


Form1:
Option Explicit
Private Sub Form_Load()
    On Error GoTo hErr
    Dim c As Class2
    Set c = New Class2
    Call c.test.test
    Debug.Print 1
    Exit Sub
hErr:
    Debug.Print 2
End Sub

结果是在打开窗口的时候,立即窗口就显示了
free
 2 
这说明对象在跳转之前就被释放了..

#43


我觉VB6中的错误处理大致可以分为几种情况:
1 最初接收到发生错误的过程,可以是一个函数,一般是在调用外部类的方法的时候产生的错误,此时可以用on error goto hErr跳转,然后在hErr中给用户处理错误的机会,这种情况一般是事件比较长,出错纪律比较大的操作,比如查询数据库OpenRecordset,复制,删除文件等.
sub somefunc()
    on error goto herr
    dim obj as class1
    set obj = new class1
    call obj.func
    ' ...
    exit sub
hErr:
    select case msgbox(err.number & ":" & err.description,vbretryignorecancel)
    case vbretry
        resume
    case vbignore
        resume next
    end select
end sub

2 在某些过程中,一些资源必须要释放,如果出现错误就需要增加错误处理:
sub somefunc2()
    on error goto herr
    dim fp as integer
    fp = freefile()
    open xxx for input as fp
    ' ...
    close fp
    exit sub
hErr:
    close fp
    call err.raise(err.number,err.description)
end sub

3 在所有的窗体的事件处理过程中,增加错误保护,提示用户产生错误,并安全返回,防止程序崩溃.
private sub Command1_Click()
    on error resume next
    call somefunc2
    ' ...
    exit sub
hErr:
    call msgbox(err.number,err.description,vbcritical)
end sub

4 在class的Terminate事件中,防止崩溃,可以使用on error resume next
private sub class_terminate
    on error resume next
    set xxx = nothing
    ' ...
end sub

#44


事件->时间
纪律->几率

#1


不能一概而论,究竟是用on error resume next 还是 on error goto,要视情况而定,一般而言,我比较喜欢用on error resume next,因为它不会因为程序错误而当掉,当调试程序想发现错误提示信息时,需要将on error resume next 暂时改为 on error goto

#2


你从哪里看来的这句话??

#3


尽量不用resume next,尽量将错误从根部拔掉。一再的将错误放行,将会导致未来的扩展和维护代价升高。

#4


Resume:恢复,并重新开始。
goto:   跳转。
使用Resume语句时,系统将清空系统错误Err对象(Err对象是个隐藏的全局变量),并重新执行程序。而goto只是跳转执行而保留错误记录,当重新产生错误时,系统就无法再次进行跳转(也无法进行恢复)
如果使用对象,可以使用on error resume next后,接着根据err.number来进行错误处理。如果想实现goto的功能,可以使用 resume Lablename 语句

#5


分三种情况:
1、有些错误需要程序处理,就用on error goto 
2、有些错误不需要处理,就用on error resume next,例如:有一个窗体内控件需要随着窗体大小的改变而改变,但是在窗体变得太小,或者最小化时,设置控件大小的语句就可能发生错误,这时就需要忽略掉错误继续执行后面的语句,on error resume next就非常适合。
3、在发生错误以后需要错误处理,但是还要继续执行后面的语句,这时也要用on error resume next语句,不过在可能发生错误的语句之后需要检查有无错误发生,并接着进行相应的处理。

#6


引用 2 楼 wallescai 的回复:
你从哪里看来的这句话??


msdn呀,就是vb6自带的帮助.

#7


2、有些错误不需要处理,就用on error resume next,例如:有一个窗体内控件需要随着窗体大小的改变而改变,但是在窗体变得太小,或者最小化时,设置控件大小的语句就可能发生错误,这时就需要忽略掉错误继续执行后面的语句,on error resume next就非常适合。
--------------------------------------------------------------------------
这本身就是需要你控制窗体最小大小的问题,而不是将错就错:)


楼主的既然看了你引用的那段,那也应该看到这一段了。

每次和对象打交道,在不知道用代码访问哪个对象时,检查一下 Err 都会打消这种疑虑。可以确定是哪个对象产生错误(Err.Source 中指定的对象),也可以确定是哪个对象将错误代码放在 Err.Number 中。

#8


学习

#9


这本身就是需要你控制窗体最小大小的问题,而不是将错就错
--------------------------------------------------
你遇到过这样的问题吗,只有你遇到过(例如在resize事件中),并且用解决它,你才知道on error resume next这一句的妙处,什么事情都不能走极端的,有那样绝对的事吗?那干嘛微软干嘛还保留这一句呢?

#10


引用 9 楼 li_yaoming 的回复:
这本身就是需要你控制窗体最小大小的问题,而不是将错就错
--------------------------------------------------
你遇到过这样的问题吗,只有你遇到过(例如在resize事件中),并且用解决它,你才知道on error resume next这一句的妙处,什么事情都不能走极端的,有那样绝对的事吗?那干嘛微软干嘛还保留这一句呢?

你遇到过这样的问题吗,只有你遇到过(例如在resize事件中),并且用解决它,你才知道on error resume next这一句的妙处
在窗体事件resize用resume next是个很妙的主意?我还是第一次听说,按窗体大小修改控件大小并不代表窗体只有宽度1时,你还要缩放你的控件宽度到0.1,这个控件不能缩到0.1,你就去缩放下一个?难道你要告诉我这个很妙?
什么事情都不能走极端的,有那样绝对的事吗
我从未说过必须,所以不绝对。
那干嘛微软干嘛还保留这一句呢?
这不是我所能解释的,我不是微软。这句代码是有些好处,我也从未全盘否定。


PS:
对事不对人,我说尽量不用resume next也只是提醒楼主少用这个语句。

#11


你在MSDN里哪个章节看到的?这段话显然是在一定的语境下说的。把你看的这篇文章的标题列出来,这样大家才好帮你解释。

另外,你在MSDN的界面里点一下“定位”那个按钮,就可以看到你现在在看的章节是属于哪本书。

#12


On Error 语句
      

启动一个错误处理程序并指定该子程序在一个过程中的位置;也可用来禁止一个错误处理程序。

语法

On Error GoTo line 

On Error Resume Next

On Error GoTo 0

On Error 语句的语法可以具有以下任何一种形式:

语句 描述 
On Error GoTo line  启动错误处理程序,且该例程从必要的 line 参数中指定的 line 开始。line 参数可以是任何行标签或行号。如果发生一个运行时错误,则控件会跳到 line,激活错误处理程序。指定的 line 必须在一个过程中,这个过程与 On Error 语句相同; 否则会发生编译时间错误。 
On Error Resume Next 说明当一个运行时错误发生时,控件转到紧接着发生错误的语句之后的语句,并在此继续运行。访问对象时要使用这种形式而不使用 On Error GoTo。 
On Error GoTo 0 禁止当前过程中任何已启动的错误处理程序。 


说明

如果不使用 On Error 语句,则任何运行时错误都是致命的;也就是说,结果会导致显示错误信息并中止运行。

一个“允许的”错误处理程序是由 On Error 语句打开的一个处理程序;一个“活动的”错误处理程序是处理错误的过程中允许的错误处理程序。如果在错误处理程序处于活动状态时(在发生错误和执行 Resume、Exit Sub、Exit Function 或 Exit Property 语句之间这段时间)又发生错误,则当前过程的错误处理程序将无法处理这个错误。控件返回调用的过程。如果调用过程有一个已启动的错误处理程序,则激活错误处理程序来处理该错误。如果调用过程的错误处理程序也是活动的,则控件将再往回传到前面的调用过程,这样一直进行下去,直到找到一个被允许的但不是活动的错误处理程序为止。如果没有找到被允许而且不活动的错误处理程序,那么在错误实际发生的地方,错误本身是严重的。错误处理程序每次将控件返回调用过程时,该过程就成为当前过程。在任何过程中,一旦错误处理程序处理了错误,在当前过程中就会从 Resume 语句指定的位置恢复运行。

注意 一个错误处理程序不是 Sub 过程或 Function 过程。它是一段用行标签或行号标记的代码。

错误处理程序依靠 Err 对象的 Number 属性中的值来确定错误发生的原因。在其它任何错误发生之前,或在调用一个可能会导致错误发生的过程之前,错误处理程序应该先测试或存储 Err 对象中相关的属性值。Err 对象中的属性值只反映最近发生的错误。Err.Description 中包含有与 Err.Number 相关联的错误信息。

On Error Resume Next 会使程序从紧随产生错误的语句之后的语句继续执行,或是从紧随最近一次调用含有 On Error Resume Next 语句的过程的语句继续运行。这个语句可以置运行时错误于不顾,使程序得以继续执行。可以将错误处理程序放置在错误发生的地方,而不必将控件传输到过程中的其它位置。在调用另一个过程时,On Error Resume Next 语句成为非活动的,所以,如果希望在例程中进行嵌入错误处理,则应在每一个调用的例程中执行 On Error Resume Next 语句。

注意 当处理在访问其它对象期间产生的错误时,与其使用 On Error GoTo 指令,不如使用 On Error Resume Next。每次和对象打交道,在不知道用代码访问哪个对象时,检查一下 Err 都会打消这种疑虑。可以确定是哪个对象产生错误(Err.Source 中指定的对象),也可以确定是哪个对象将错误代码放在 Err.Number 中。

On Error GoTo 0 停止在当前过程中处理错误。即使过程中包含编号为 0 的行,它也不把行 0 指定为处理错误的代码的起点。如果没有 On Error GoTo 0 语句,在退出过程时,错误处理程序会自动关闭。

在错误未发生的时候,为了防止错误处理程序代码运行,请像在下段程序中那样,在紧靠着错误处理程序的前面写入 Exit Sub、Exit Function 或 Exit Property 语句。

Sub InitializeMatrix(Var1, Var2, Var3, Var4)
   On Error GoTo ErrorHandler
   . . .
   Exit Sub
ErrorHandler:
   . . .
   Resume Next
End Sub

此处,错误处理程序代码在 Exit Sub 语句之后,而在 End Sub 语句之前,从而与过程中的流程分开。错误处理程序代码可以在程序中的任何地方写入。

当对象作为文件运行时,对象中未捕获的错误都被返回控制应用程序。在开发环境中,如果设置了正确选项,未捕获的错误只返回控制应用程序。请参考主应用程序的文档的有关描述,从而得知,在调试时应该设置哪些选项、如何设置这些选项以及主机能否建立类。

如果建立一个访问其它对象的对象,则应该着手处理从那些对象返回的未处理错误。如果无法处理这种错误,请将 Err.Number 中的错误代码当作自己的一个错误,然后将错误回传给对象的调用者。应该将错误代码添加到 vbObjectError 常数上来指定这个错误。举例来说,如果错误代码为 1052,则使用如下方法指定错误:

Err.Number = vbObjectError + 1052

注意 调用动态链接库 (DLL) 期间产生的系统错误不会产生例外情况,也不会被 Visual Basic 的错误捕获操作所捕获。当调用 DLL 函数时,应该(根据 API 的详细说明)检查每一个返回值以确定是成功还是失败,如果失败,则检查 Err 对象的 LastDLLError 属性中的值。

#13


Private Sub pic_left_Resize()
On Error Resume Next
    dg_result.Height = pic_left.Height - 400
    dg_result.Width = pic_left.Width - 60
End Sub
这是我程序中的一个resize事件,在改变窗口大小,pic_left.Height - 400小于零时,就会发生异常,产生错误,在程序中是没有必要处理这样的错误的,所以用On Error Resume Next,我想,大家遇到这样的问题也会采用一样的方式的。
次之,vc中有try--catch语句,vb中有了On Error Resume Next才能得到相同的效果。
注意:我也是对事不对人的,大家互相学习讨论,谁对谁错没有那么重要,不要误解。

#14


引用 13 楼 li_yaoming 的回复:
...

不多说了,偏离了楼主主题太远了 :)

#15


看来是是在看《参考手册》里On Error语句的内容。

我的MSDN是英文版的,给你找到了对应的英文句子。


访问对象时要使用这种形式而不使用 On Error GoTo。
Use this form  rather than On Error GoTo when accessing objects.


当处理在访问其它对象期间产生的错误时, 与其使用 On Error GoTo 指令, 不如使用 On Error Resume Next。
The On Error Resume Next construct may be  preferable to On Error GoTo when handling errors generated during access to other objects. 

从这两段话的英文原文来看,MSDN是在给出 建议,而不是硬性规定。

#16


但是为何要给出这样的建议,我好像也没看懂,和楼主一起等其他朋友来指点。

下面是MSDN给出的例子,我在想,在用On Error Resume Next的地方用On Error GoTo ErrorHandler也没什么不好啊?

Sub OnErrorStatementDemo()
   On Error GoTo ErrorHandler   ' Enable error-handling routine.
   Open "TESTFILE" For Output As #1   ' Open file for output.
   Kill "TESTFILE"   ' Attempt to delete open 
            ' file.
   On Error Goto 0   ' Turn off error trapping.
   On Error Resume Next   ' Defer error trapping.
   ObjectRef = GetObject("MyWord.Basic")   ' Try to start nonexistent
            ' object, then test for 
'Check for likely Automation errors.
   If Err.Number = 440 Or Err.Number = 432 Then
      ' Tell user what happened. Then clear the Err object.
      Msg = "There was an error attempting to open the Automation object!"
      MsgBox Msg, , "Deferred Error Test"
      Err.Clear   ' Clear Err object fields 
   End If   
Exit Sub      ' Exit to avoid handler.
ErrorHandler:   ' Error-handling routine.
   Select Case Err.Number   ' Evaluate error number.
      Case 55   ' "File already open" error.
         Close #1   ' Close open file.
      Case Else
         ' Handle other situations here... 
   End Select
   Resume   ' Resume execution at same line
            ' that caused the error.
End Sub


MSDN对上述例子的说明:This example first uses the On Error GoTo statement to specify the location of an error-handling routine within a procedure. In the example, an attempt to delete an open file generates error number 55. The error is handled in the error-handling routine, and control is then returned to the statement that caused the error. The On Error GoTo 0 statement turns off error trapping. Then the On Error Resume Next statement is used to defer error trapping so that the context for the error generated by the next statement can be known for certain. Note that Err.Clear is used to clear the Err object's properties after the error is handled.

#17


AC和li_yaoming,你们可能还真没讨论到点儿上。MSDN的意思似乎并不是说用了On Error Resume Next之后就不处理错误了,而只是 Defer error trapping

至于为何在处理和访问对象相关的错误时defer比直接跳转好,MSDN却没有给出说明。

#18


这话的意思是 On Error Resume Next 可以在错误发生后马上处理。
比较下面两种方式(用 a、b、c 代替错误号)
Sub Main()
    On Error Resume Next

    Call Sub1
    If Err.Number <> 0 Then
        Select Case Err.Number
            Case a:     MsgBox "Sub1 发生 AAA 错误"
            Case b:     MsgBox "Sub1 发生 BBB 错误"
            Case Else:  MsgBox "Sub1 发生未知错误 " & Err.Number
        End Select
        Exit Sub
    End If

    Call Sub2
    If Err.Number <> 0 Then
        Select Case Err.Number
            Case a:     MsgBox "Sub1 发生 AAA 错误"
            Case c:     MsgBox "Sub2 发生 CCC 错误"
            Case Else:  MsgBox "Sub2 发生未知错误 " & Err.Number
        End Select
        Call cancel1
    End If
End Sub

Sub Main()
    On Error GoTo ErrHandler
    Dim iStep As Long
    Dim sStepName As String
    
    iStep = 1
    Call Sub1
    iStep = 2
    Call Sub2
    
ExitEntry:
    Exit Sub
ErrHandler:
    sStepName = Choose(iStep, "Sub1", "Sub2")
    Select Case Err.Number
        Case a:     MsgBox sStepName & " 发生 AAA 错误"
        Case b:     MsgBox sStepName & " 发生 BBB 错误"
        Case c:     MsgBox sStepName & " 发生 CCC 错误"
        Case Else:  MsgBox sStepName & " 发生未知错误 " & Err.Number
    End Select
    If iStep = 2 Then
        Call cancel1
    End If
    Resume ExitEntry
End Sub

#19


我猜测一个可能的原因是因为来自对象的错误编号也许会和其他的错误编号搞混,所以不把相关的错误处理放在ErrorHandler,而是放在紧随其后的代码里,像16楼的例子里那样。

从4楼的回复来看,坏上帝也很熟悉这种用法。

#20


Tiger_Zhao,你的理解正确,可是你也没说明为什么这样做更好?

#21


关键是类似错误发生后的 Cancel1() 调用,不同步骤有不同处理,步骤多的话顺序结构比较清晰。

#22


这跟 对象有什么关系?貌似没说到 点子上(再次模仿chenhui说,嘿嘿)

#23


我觉得对MSDN不必咬文嚼字,或许是翻译造成的歧意,错误处理那有什么定式.....一切都根据需要来处理
On Error Resume Next用于忽略错误或者嵌入错误处理的场合,一定要把那个objects之类的翻译为对象或者理解成VB中我们常规认识的对象那就钻牛角尖吧....不要说我误导,个人观点而已....

#24


引用 22 楼 slowgrace 的回复:
这跟对象有什么关系?貌似没说到点子上(再次模仿chenhui说,嘿嘿)

老鸟是写的错误处理范例,MSDN推荐使用resume next进行错误处理。

#25


如果你有以下需求:
1)不在乎程序中的出错,或者说你觉得你可以保证程序没有任何错误、甚至连语法错误也没有;
2)即使出错了你也不想让自己知道更不想让别人知道;
3)测试结果表明程序有问题也不想快速定位出错位置;
那么恭喜你:
你完全可以用“on error resume next”。

但是,
如果你是:
1)严格要求自己写出好程序;
2)想保证编译后不出简单错误,比如说简单的变量未定义错误,不愿意让客户或上级找到你所写程序的根本不应该出现的最简单错误;
3)如果出错的话,能快速定位出错位置,快速找到出错原因--即使最后表明是因为别人出了错;
那么很抱歉,
你最好:
1)尽量少用“on error resume next”,但也不排除在需要的时候技巧性地使用“on error resume next”--比如说在你可预知的错误出现前使用“on error resume next”;
2)在使用“on error goto xxx”的xxx处,有相应的错误信息输出到文件或终端,并且视客户要求在出错以后选择使用“resume next”或“Exit Sub”或“Exit Function”;

#26


引用楼主 kanzm 的回复:
为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?
以下是msdn的原文,
 On Error Resume Next 说明当一个运行时错误发生时,控件转到紧接着发生错误的语句之后的语句,并在此继续运行。访问对象时要使用这种形式而不使用 On Error GoTo。

 我不明白为什么这样说,访问对象为何就要忽略错误呢,不能用 on error goto 呢?


MSDN并不是神,
这方面它写得其实并不好的。

实际上,
乱用“on error resume next”的话很容易让人陷入歧途。
原因很简单,
“on error resume next”的意思就是:出错后什么也不管,继续执行下一句。

#27


调用者(Caller) 无论从中文还是英文都看起来像个对象,可是无对象的纯过程也可以叫做调用者。

技术文档不是字典,不能咬文嚼字。

#28


引用 15 楼 slowgrace 的回复:
看来是是在看《参考手册》里On Error语句的内容。

 我的MSDN是英文版的,给你找到了对应的英文句子。


 访问对象时要使用这种形式而不使用 On Error GoTo。
 Use this formrather thanOn Error GoTo when accessing objects.


 当处理在访问其它对象期间产生的错误时,与其使用 On Error GoTo 指令,不如使用 On Error Resume Next。
 The On Error Resume Next construct may bepreferableto On Error GoTo when handling errors generated during access to other objects.

 从这两段话的英文原文来看,MSDN是在给出建议,而不是硬性规定。

这都may be preferable了,就是个建议
我个人的理解,由于vb没有.net那种结构化错误处理。
on error resume next给了一个在后面代码中根据err.number作判断的机会,或者直接忽略进行以后的动作
on error goto ...也是一种错误处理方式,需要跳过中间一段代码
具体哪个时候用哪个实在太灵活了,而且也没有硬性规定哪个好
函数中可以出现

private sub Func()
 on error resume next 
 ....
 ....
 if err.number... then
 end if 
 on error goto errhandler
 ...

errhandler
end sub

#29


你的Caller从哪里冒出来的?你看我在15楼引用的原文。

我的 结论
On Error Resume Next实际上通常有两种用法:一种是用来忽略错误(比如13楼);一种是用来随后立即处理错误但却保持顺序的程序结构(比如18楼)。

我想,理解了通常在什么情况下用这两种用法也就可以了。至于MSDN这两段让人费解的话,也许我们暂且可以理解它是一个概念不清的文档写作者写的(比如像我这样的,呵呵),可以不必理会。

#30


29楼第一句回给赵老虎的。

#31


虽然经大家劝说,俺打算放弃这题了。不过的话,你们看看下面这段话,会不会和上面的话有点关联?

“Unhandled errors in event procedures will be fatal to your control component, and the application using it, because there will never be a procedure on the call stack that can handle the errors.”

这段话是针对ActiveX Control说的。

#32


MSDN里只是一种"技巧建议",并非"必须的语法"吧.

实际情况很复杂,不能一概而论.

#33


引用 29 楼 slowgrace 的回复:
你的Caller从哪里冒出来的?你看我在15楼引用的原文。

只是举例,我们平时的用词就经不起咬文嚼字。

#34


请教你这个: http://topic.csdn.net/u/20090730/09/0a31adcc-6948-4331-8042-067774134722.html?seed=1008754042&r=58901954#r_58901954

olb文件在VB里可以引用,也看到ACCESS的对象库了,但是在部件里却找不到它的踪影。(那边我不能回复了:)

#35


对象变量的使用,可能是多种形式,存在着使用后立刻释放的情况
在极端情况下对于对象的对象的引用,是动态引用的,vb的调用方式是,调用后立刻释放
如果此时转移代码,猜想,可能造成对象无法释放,原因是释放语句在调用语句之后

做个测试

class1:
property get GetUserObject(byval index as long)as class2
   if .. index 有效 set GetUserObject = xxxx
end 。。。

class2:
过程略,在类的初始化和退出过程加个 debug.print 可以清楚的看到效果


当用 on error goto 时,错误发生在对象内部,被调用函数截获,会立刻执行转移
这时释放 GetUserObject 所获取的对象本应在调用后立刻释放,但被转移了,释放过程被忽略了

如果用 on error resume nexe 就会同msdn所述,继续下一条语句,这条语句就应该是释放了

如果释放未执行,则对象引用计数是无法消减的,被引用的对象就可能会无法真正的退出。

只是个人意见,大家酌情参考。。。
我只是觉得,能做vb的人肯定也想到了各种各样的问题,而且自动编译器,不一定能智能到,自动掌握所有用户代码形式,有些非常*的代码形式,恐怕还得手动做。。。

#36


为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?
我的意思好像没有说清
大概意思就是,因为对象的特点,以及程序应追求的正确申请释放资源的原则来讲,对于 on error goto 和
on error resume next 应为有区别使用。
上面我回贴的内容仅仅是列举了一种,需要使用 on error resume next 来处理的情况,当然肯定还会有很多

#37


呵呵,好久没见了 为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?

这个解释疑似靠谱 为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?,待我试试。

#38


如果程序中使用了多个同一个类型的对象,它们的err.number,err.source等都是相同的,在errorhandler中难以区别是程序中具体哪一个对象引发的。而用on error resume next,就能解决这个问题。

#39


具体怎么用这个得具体问题具体分析,并不像楼主所理解的那样。
个人对这两个语句的理解:
1、On Error Resume Next :触发错误,忽略它,继续执行
2、On Error GoTo xxx:触发错误,跳转到指定的位置:xxx

#40


引用 37 楼 slowgrace 的回复:


为什么访问对象时,要用on error resume next 而不能用 on error goto 呢?

#41


引用 39 楼 veron_04 的回复:
具体怎么用这个得具体问题具体分析,并不像楼主所理解的那样。
 个人对这两个语句的理解:
 1、On Error Resume Next :触发错误,忽略它,继续执行
 2、On Error GoTo xxx:触发错误,跳转到指定的位置:xxx

 1、On Error Resume Next :触发错误,忽略它,继续执行
================
在继续执行时,下面的语句可以就是错误处理语句。


On Error GoTo xxx:触发错误,跳转到指定的位置:xxx
================
理论上,只要愿意,在这里也不进行任何实质的错误处理。

#42


引用 35 楼 pctgl 的回复:
对象变量的使用,可能是多种形式,存在着使用后立刻释放的情况
在极端情况下对于对象的对象的引用,是动态引用的,vb的调用方式是,调用后立刻释放
如果此时转移代码,猜想,可能造成对象无法释放,原因是释放语句在调用语句之后

做个测试

class1:
property get GetUserObject(byval index as long)as class2
  if .. index 有效 set GetUserObject = xxxx
end 。。。

class2:
过程略,在类的初始化和退出过程加个 debug.print 可以清楚的看到效果


当用 on error goto 时,错误发生在对象内部,被调用函数截获,会立刻执行转移
这时释放 GetUserObject 所获取的对象本应在调用后立刻释放,但被转移了,释放过程被忽略了

如果用 on error resume nexe 就会同msdn所述,继续下一条语句,这条语句就应该是释放了

如果释放未执行,则对象引用计数是无法消减的,被引用的对象就可能会无法真正的退出。

只是个人意见,大家酌情参考。。。
我只是觉得,能做vb的人肯定也想到了各种各样的问题,而且自动编译器,不一定能智能到,自动掌握所有用户代码形式,有些非常*的代码形式,恐怕还得手动做。。。



Class1:
Option Explicit

Public Sub test()
    Err.Raise 1
End Sub

Private Sub Class_Terminate()
    Debug.Print "free"
End Sub


Class2:
Option Explicit

Property Get test() As Class1
    Set test = New Class1
End Property


Form1:
Option Explicit
Private Sub Form_Load()
    On Error GoTo hErr
    Dim c As Class2
    Set c = New Class2
    Call c.test.test
    Debug.Print 1
    Exit Sub
hErr:
    Debug.Print 2
End Sub

结果是在打开窗口的时候,立即窗口就显示了
free
 2 
这说明对象在跳转之前就被释放了..

#43


我觉VB6中的错误处理大致可以分为几种情况:
1 最初接收到发生错误的过程,可以是一个函数,一般是在调用外部类的方法的时候产生的错误,此时可以用on error goto hErr跳转,然后在hErr中给用户处理错误的机会,这种情况一般是事件比较长,出错纪律比较大的操作,比如查询数据库OpenRecordset,复制,删除文件等.
sub somefunc()
    on error goto herr
    dim obj as class1
    set obj = new class1
    call obj.func
    ' ...
    exit sub
hErr:
    select case msgbox(err.number & ":" & err.description,vbretryignorecancel)
    case vbretry
        resume
    case vbignore
        resume next
    end select
end sub

2 在某些过程中,一些资源必须要释放,如果出现错误就需要增加错误处理:
sub somefunc2()
    on error goto herr
    dim fp as integer
    fp = freefile()
    open xxx for input as fp
    ' ...
    close fp
    exit sub
hErr:
    close fp
    call err.raise(err.number,err.description)
end sub

3 在所有的窗体的事件处理过程中,增加错误保护,提示用户产生错误,并安全返回,防止程序崩溃.
private sub Command1_Click()
    on error resume next
    call somefunc2
    ' ...
    exit sub
hErr:
    call msgbox(err.number,err.description,vbcritical)
end sub

4 在class的Terminate事件中,防止崩溃,可以使用on error resume next
private sub class_terminate
    on error resume next
    set xxx = nothing
    ' ...
end sub

#44


事件->时间
纪律->几率