Error handling 如何重构VB6代码以防止运行时错误

Error handling 如何重构VB6代码以防止运行时错误,error-handling,vb6,runtime-error,Error Handling,Vb6,Runtime Error,VB6应用程序在多个位置遇到运行时错误 我知道这是错误处理不好的结果,但是否可以分析代码以查看其易受运行时错误影响的地方?任何应用程序都易受运行时错误影响,因为在调用外部资源时没有错误处理,所以您可以先确定这些点 我使用了一个免费的工具(很多年前),可以将错误处理追溯到VB6代码,它至少可以记录错误及其发生的时间点 下面是:VB6应用程序中运行时错误的常见来源包括 访问不存在的集合中的密钥 对无对象调用方法或属性 当字符串为空时,使用CLng将字符串转换为数字 访问超出其长度的数组(例如在调用

VB6应用程序在多个位置遇到运行时错误


我知道这是错误处理不好的结果,但是否可以分析代码以查看其易受运行时错误影响的地方?

任何应用程序都易受运行时错误影响,因为在调用外部资源时没有错误处理,所以您可以先确定这些点

我使用了一个免费的工具(很多年前),可以将错误处理追溯到VB6代码,它至少可以记录错误及其发生的时间点


下面是:

VB6应用程序中运行时错误的常见来源包括

  • 访问不存在的集合中的密钥
  • 对无对象调用方法或属性
  • 当字符串为空时,使用CLng将字符串转换为数字
  • 访问超出其长度的数组(例如在调用Split之后,然后假设字符串具有您期望的片段数)
因此,除了执行其他人的建议并分析实际错误的来源之外,您还可以从在代码中查找类似的区域并在其周围放置适当的错误处理开始。请记住,最好的“错误处理”通常根本不涉及使用On error,而是通过检查这些边界情况来提前防止错误,如

  • 如果不是的话,对象什么都不是
  • 如果Len(字符串)>0
  • 如果UBound(数组)>x

等等。

您需要确保代码库中的每个方法(函数、子函数、属性…)都有一个错误处理语句。可能不是每个人都能生成运行时错误,但这将在不进行大量前期分析的情况下防止应用程序崩溃

确保在任何可执行代码行之前都有一条语句,上面写着“On Error GoTo…”和一个标签,然后确保将该标签和一些错误处理代码放在方法的底部。我使用了一个名为的免费工具,它允许您自动包含此文本。选项中有一个错误处理程序选项卡,允许use指定要放入的文本和位置。这就是我的样子:

    On Error GoTo l{PROCEDURE_NAME}_Error

    {PROCEDURE_BODY}

    Exit {PROCEDURE_TYPE}

l{PROCEDURE_NAME}_Error:

    LogError "{MODULE_NAME}", "{PROCEDURE_NAME}", Err, Err.Description

然后,我只需确保LogError函数存在,并将错误写入日志文件,以便我查看。

这里有一些很好的答案,包括
关于错误转到的建议和常见错误

但可能会扩大范围,利用内置工具来分析断点、监视表达式等代码,特别适合调试运行时错误、局部窗口(在调试中经常被忽略,但功能非常强大)和调用堆栈。你可以从这里获得很多关于这方面的信息:

考虑其他可能有用的事情:

  • 投资一个能帮助你的工具 具有类似或的分析
  • 尝试移植现有的应用程序 到VB.NET-不实际移植和 使用,但查看转换日志 对于需要修复的事情

  • 按照Ryan的回答和回复中的注释,您不必在每个例程中都进行错误处理,只需在每个事件和
    Sub Main()
    (以及API回调,如果它们还没有)

    API回调是指Win32API直接调用的例程,通常使用
    AddressOf
    传递给
    声明的
    函数。(即,在代码中搜索
    AddressOf
    ,并确保作为参数提及的所有例程都具有捕获错误的错误处理程序,并且不允许它们尝试冒泡。)


    我刚刚注意到,这并没有真正回答最初提出的问题(尽管给出了对Ryan回答的评论,这是一个很好的第一步):一旦您在每个事件中进行了错误处理,等等,您将捕获所有错误,但您无法直接分析所有错误发生的位置。您需要将错误日志至少扩展到记录错误的事件所调用的所有例程,以便更准确地定位每个错误的确切来源。

    在VB6中,当调用事件函数而不进行错误处理时,就会发生运行时错误。因此,至少您的所有事件处理函数(如Form.Open())都应该由错误处理程序包围(是的,我知道VB6没有),可以像这样很好地实现(我们在所有应用程序中都这样做):

    将其用作每个事件处理函数的第一行(它是一个大的有效标签,用于在末尾设置On Error):

    现在,在所有这些功能结束时使用此选项:

    ¦____________________________________________________________________________________________________________________________________: Exit Sub
    ErrorHandler: handleError CodeDb, "Form_frm_filter_deletecolum", "cmd_deletecolum_Click", err.Number, err.description, err.Source, err.LastDllError, err.Helpfile, err.HelpContext, Erl: err.Clear
    
    但是用模块名和函数名替换这两个字符串。并将错误转到0时的每个
    替换为错误转到ErrorHandler时的

    现在用给定的参数创建一个函数handleError(在我的应用程序中,它会自动将错误报告发送到我们的错误跟踪系统),并显示一条漂亮的错误消息

    我们甚至更进一步,通过一个预构建的过程,将类似的行添加到所有其他函数(意味着非事件函数,或其他函数刚刚调用的函数),以记住发生错误的行,并累积完整的堆栈跟踪(是的,VB6中的stacktraces!)。此外,此过程会将行号添加到每一行,以便在错误处理程序的Erl部分中给出行号


    我们的工具是作为一些MS访问模块编写的,所以我不能简单地为您提供它,但您可以看到您必须去哪里获取它

    我的问题是,代码中已经混杂了各种错误处理技术,我不想打乱代码中有意忽略错误的任何部分。您的建议是否会使代码的功能与以前完全相同,但会记录错误?这将记录它遇到的每个错误。如果存在故意忽略错误的部件,请使用On Error
    ¦____________________________________________________________________________________________________________________________________: Exit Sub
    ErrorHandler: handleError CodeDb, "Form_frm_filter_deletecolum", "cmd_deletecolum_Click", err.Number, err.description, err.Source, err.LastDllError, err.Helpfile, err.HelpContext, Erl: err.Clear