【问题标题】:What line(s) this code might throw a "Index was outside the bounds of the array" exception?此代码的哪一行可能会引发“索引超出数组范围”异常?
【发布时间】:2010-12-22 11:26:56
【问题描述】:

有关此错误的一些背景知识:客户在其日志文件中收到此错误消息,支持人员尚未能够重现它。所以我正在审查代码,试图确定可能发生的情况。我通过查看他们的日志文件将其缩小到代码的这一部分。我没有编写此代码,但其目的是将 zip 文件 ftp 到远程服务器。所以问题是......

此代码的哪一行可能会引发“索引超出数组边界”异常?

FtpLib.FTPFactory ff = new FtpLib.FTPFactory();
try

{
    ff.setRemoteHost(job.FTPHost);
    ff.setRemoteUser(job.FTPUser);
    ff.setRemotePass(job.FTPPW);
    ff.login();
// Execute misc. extra commands
foreach (string command in job.Commands)
{
    if (log.IsDebugEnabled)
        log.Debug("JOB: " + job.ID + " --    FTP Command \"" + command + "\" sent...");

    ff.sendCommand(command);

    if (log.IsDebugEnabled)
        log.Debug("JOB: " + job.ID + " --       Response: " + ff.getLastMessage());
}

try
{
    ff.mkdir(job.FTPRemoteDir);
}
catch (IOException) { }

ff.chdir(job.FTPRemoteDir);
ff.setBinaryMode(true);

if (log.IsInfoEnabled)
    log.Info("JOB: " + job.ID + " --    FTP UPLOAD: \"" + zipfile.Name + "\" to \"" + job.FTPHost + "/" + job.FTPRemoteDir + "/\"");
ff.upload(zipfile.FullName);
if (log.IsInfoEnabled)
    log.Info("JOB: " + job.ID + " --       Completed.");

bFTPSuccess = true;
break;

}

提前致谢!

更新: 我想我们都同意问题出在 FTPLib 中,我会看看我们是否有它的来源。我发现这是一个晦涩难懂的错误,客户甚至无法始终如一地重现,所以这将是一个有趣的重点。我使用 Exception.StackTrace 和 Exception.ToString 函数添加了额外的调试日志记录。问题解决后我会再次更新,并尝试将正确答案奖励给正确的人,尽管每个人都提出了很好的建议。感谢您的帮助!

【问题讨论】:

  • 这是什么语言?您应该将语言放在标签中。
  • 哎呀,我以为我添加了 c#,但一定是不小心删除了它。我会解决的,谢谢。

标签: c# arrays exception


【解决方案1】:

基本上每个方法调用都是可能的候选者,包括构造函数和属性。 (它们基本上是方法调用)最后两个可能是风险最低的(这将是一个奇怪的实现)

我会说最合理的是 ff.getLastMessage()

【讨论】:

    【解决方案2】:

    我建议您在当前捕获越界异常的位置记录 Exception.StackTrace。 Exception.ToString() 也非常有用,因为它提供了大部分重要信息。这应该告诉您抛出异常的确切位置(无需猜测)。但是请注意捕获异常并将其隐藏的代码-我看到您发布的代码具有“catch (IOException) {}”。还要警惕捕获异常然后抛出不同异常的代码,这将掩盖原始错误。

    应该不需要在 try...catch 中包含可疑的单个行 - 只要在调用链中的某个点捕获并记录任何异常。

    【讨论】:

    • 我同意,看来这个 FTPLib 过于依赖异常。我会看看那个代码。现在我听取了您的建议并将 StackTrace 和 ToString 添加到日志文件中。
    【解决方案3】:

    为了完整起见,除了 Will 的帖子:

    FtpLib.FTPFactory ff = null; 尝试 { ff = 新的 FtpLib.FTPFactory(); } 捕获(异常前) { // 记录下来 }

    另外,我不禁想知道,登录是否正常工作,这是在 try/catch 块中包装它的另一个地方

    尝试 { ff.login(); } 捕获(异常前) { // 记录它。 }

    可能是登录失败,ff 被用于执行命令,可能会抛出异常 - 不要问为什么?我怀疑这个 FTP 例程是由不知道发生了什么或写得不好的人编写的,请查看登录方法 - 全部小写,正如上面 Will 提到的(指出这一点的荣誉)。

    希望这会有所帮助并祝您愉快地寻找错误... 最好的祝福, 汤姆。

    【讨论】:

      【解决方案4】:

      没有什么明显的。它将归结为 FtpFactory 的实际实现(我对可能原因的投票)和日志。

      如果创建这些类型的成本很高,工厂可能会保留其创建的类型的实例数组。因此,当您第一次执行可能需要使用其中一个实例(“ff.login”)的操作时,可能会暴露该错误。

      我建议您使用 try/catch 包围任何使用工厂的尝试,并在日志中记录它发生的位置。另外,我建议无论如何不要使用该工厂,因为它是由很少考虑标准和实践(小写方法名称?)的人编写的,这是做工不佳的警告信号。

      tl;dr:不要相信你的 ftp 工厂。可能很烂。

      【讨论】:

        【解决方案5】:
        ff.getLastMessage()
        

        那个方法有什么作用?它如何获得最后一条消息?如果它使用类似messages[messages.Count - 1] 或类似的东西,并且消息集合是空的,它会抛出该错误。这是我最好的猜测。

        【讨论】:

          【解决方案6】:

          我不认为是那些代码行。

          我的第一个猜测是你的 foreach 循环中的一些东西,但这看起来很可靠。

          你确定它在代码的一部分吗?

          你能粘贴堆栈跟踪吗?

          【讨论】:

          • 我们还没有重现它,所以我无法粘贴确切的堆栈跟踪。不过我会看看我能做些什么。
          • 啊,那是你的问题......你可能整天都在追逐幻影代码,却不知道具体在哪里看。我认为你的时间最好花在重现错误并尝试从那里解决它,而不是猜测你可能出错的地方。虽然这很难,但当难以重现错误时,我讨厌它。祝你好运。
          • 发现客户甚至无法重现错误。在过去的几个月里它只发生了 3 次 LOL。有趣。
          • 哈哈,我讨厌这样。如果有一天你真的可以重现它,那么祝你好运。
          【解决方案7】:

          如果不知道可能很难分辨的其余代码。对我来说突出的线是:

          ff.getLastMessage()
          

          但这只是一个有根据的猜测(例如,如果消息存储在一个数组或类似的数组中,最后从中提取)

          【讨论】:

            猜你喜欢
            • 2019-04-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-05
            • 2012-11-01
            • 1970-01-01
            相关资源
            最近更新 更多