4

VB6 应用程序在多个地方遇到运行时错误。

我知道这是错误处理不佳的结果,但是是否可以分析代码以查看它在哪些地方容易受到运行时错误的影响?

4

6 回答 6

3

任何应用程序都容易受到运行时错误的影响,因为对外部资源的调用没有错误处理,因此您可以将这些点确定为开始。

我使用了一个免费工具(很多年前),它可以对 VB6 代码进行错误处理,这至少会记录错误及其发生的点。

这是:用于在 VB6 中轻松处理错误的 HuntErr 插件

于 2010-05-09T06:50:49.887 回答
2

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

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

    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 函数存在并将错误写入我可以查看的日志文件。

于 2010-05-14T16:34:41.450 回答
1

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

  • 访问集合中不存在的键
  • 调用什么都不是对象的方法或属性
  • 当字符串为空时,使用 CLng 将字符串转换为数字
  • 访问超出其长度的数组(例如在调用 Split 然后假设字符串具有您期望的数量)

因此,除了按照其他人的建议进行分析并分析实际错误的来源之外,您还可以首先在代码中查找诸如此类的区域并在它们周围进行适当的错误处理。请记住,通常最好的“错误处理”根本不涉及使用 On Error,而是通过检查这些边界情况来提前防止错误,例如

  • 如果不是对象什么都不是
  • 如果 Len(string) > 0
  • 如果 UBound(array) > x

ETC...

于 2010-05-13T14:10:29.180 回答
0

这里有一些很好的答案,包括On Error GoTo建议和bwarner提到的裂缝中的常见错误。

但也许可以扩大范围并利用内置工具来分析断点、监视表达式等代码,特别适用于调试运行时错误、本地窗口(在调试中经常被忽略,但非常强大)和调用堆栈。你可以从这里得到很多很好的信息:调试你的代码和处理错误

其他需要考虑的事情可能会有所帮助:

  1. 投资一个可以帮助您进行分析的工具,例如CodeSMART 2009 for VB6VB Project Analyzer
  2. 尝试将现有应用程序移植到 VB.NET - 不是实际移植和使用,而是查看转换日志以查找需要修复的内容。
于 2010-05-15T06:38:04.883 回答
0

按照 Ryan 的回答和回应的评论,您不必每个例程中放置错误处理,只需在每个 Event 和Sub Main()(以及 API 回调,如果他们还没有的话)。

API 回调是指由 Win32API 直接调用的例程,通常Declared使用AddressOf. (即搜索你的代码AddressOf并确保所有作为参数提到的例程都有错误处理程序来捕获错误并且不允许它们尝试冒泡。)

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

于 2010-05-18T11:58:57.850 回答
0

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

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

¦¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯: On Error GoTo ErrorHandler:

现在在所有这些功能的末尾使用它:

¦____________________________________________________________________________________________________________________________________: 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

但是用模块名称和函数名称替换这两个字符串。并将每个替换On Error Goto 0On Error Goto ErrorHandler.

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

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

我们的工具是作为一些 MS Access 模块编写的,所以我不能简单地为您提供它,但您知道您必须去哪里。

于 2010-05-18T21:05:31.593 回答