Delphi 有没有一种有效的方法可以不用尝试就可以防弹一个程序?

Delphi 有没有一种有效的方法可以不用尝试就可以防弹一个程序?,delphi,exception,Delphi,Exception,我有一个Delphi 6客户机服务器应用程序,其中服务器基本上是: initialize; repeat try getInput; putOutput; except on e: exception do writeln(e.message); end until false; 在开发过程中,诸如指针异常之类的错误很少出现,但服务器可以继续运行。现在,服务器已经投入生产,似乎已经调试完毕,很有可能会删除try…因为它会给服务器增加大量的执行开销,但是如果发

我有一个Delphi 6客户机服务器应用程序,其中服务器基本上是:

initialize;
repeat
  try
    getInput;
    putOutput;
  except
    on e: exception do writeln(e.message);
  end
until false;
在开发过程中,诸如指针异常之类的错误很少出现,但服务器可以继续运行。现在,服务器已经投入生产,似乎已经调试完毕,很有可能会删除try…因为它会给服务器增加大量的执行开销,但是如果发生异常,它会停止服务器

一种解决方案是让父进程简单地重新启动整个服务器,并且在重新启动时绕过初始化将有效地复制尝试…除了已完成,但不会有导致异常的任何记录,并且在有或没有初始化的情况下重新启动实际上会产生许多不必要的状态问题,尤其是客户端连接

是否有某种方法可以覆盖或修改异常处理,以便在异常发生时,在程序退出并重新启动之前,它会记录在系统事件日志或%errorlevel%的某个位置:恢复,但不会产生全面尝试的开销…除了


理想的解决方案是记录异常,但在重复级别继续执行…直到。也许通过将repeat的地址保存在某个可访问的全局文件中,然后使任何异常解除调用堆栈并恢复到保存的地址?我猜这就是我们所做的。除了基本上是这样做的,但是有没有一种方法可以避免在没有例外的情况下它所带来的开销呢?

扩展Serg的建议:

repeat
  try
    repeat
      getInput;
      putOutput;
    until false;
  except
    on e: exception do writeln(e.message);
  end
until false;
具有相同的行为,但会移动尝试。。除了最里面的循环之外


然而,如果这对性能有任何明显的影响,我会感到惊讶

扩展Serg的建议:

repeat
  try
    repeat
      getInput;
      putOutput;
    until false;
  except
    on e: exception do writeln(e.message);
  end
until false;
具有相同的行为,但会移动尝试。。除了最里面的循环之外


然而,如果这对性能有任何明显的影响,我会感到惊讶

扩大David和Sergs的建议

如果循环的复杂性与发布的代码所建议的一样低,或者可以降低到如此简单的程度,那么提供这两种行为可能是可行的,这取决于通过异常处理启用或禁用运行时错误的命令行开关

在启动时解析命令行以确定操作模式,并相应地设置指示符变量。e、 g使用枚举:

type
  TServerMode = (smHighThroughput, smDiagnostic);

var
  ServerMode: TServerMode;


if FindCmdLineSwitch('d') then
   ServerMode := smDiagnostic
else
   ServerMode := smHighThroughput;
如果命令行参数出于任何原因不可取或不实用,您当然可以在配置文件或数据库表中使用设置

无论您如何操作,您都可以在高吞吐量模式或可恢复诊断模式下运行服务器,并使用最少的重复语法:

try
  case ServerMode of
    smDiagnostic     : repeat
                         try
                           getInput;
                           putOutput;
                         except
                           on e: Exception do .... // etc      
                         end;
                       until FALSE;

    smHighThroughput : repeat
                         getInput;
                         putOutput;
                       until FALSE;
  end;

except
  on e: Exception do .... // etc      
end;
请注意,即使在高吞吐量模式下,上面的示例也捕获有关导致服务器终止的任何异常的信息。诊断模式记录所有异常,但尝试保持服务器运行

然后,如果需要诊断异常不稳定的服务器,您可以使用启用诊断模式的选项将其默认为高通量模式


话虽如此,我还是会尝试对尝试的影响进行明确的量化。除了在循环上,然后再花很大的精力来设计这种影响。

进一步阐述David和Sergs的建议

如果循环的复杂性与发布的代码所建议的一样低,或者可以降低到如此简单的程度,那么提供这两种行为可能是可行的,这取决于通过异常处理启用或禁用运行时错误的命令行开关

在启动时解析命令行以确定操作模式,并相应地设置指示符变量。e、 g使用枚举:

type
  TServerMode = (smHighThroughput, smDiagnostic);

var
  ServerMode: TServerMode;


if FindCmdLineSwitch('d') then
   ServerMode := smDiagnostic
else
   ServerMode := smHighThroughput;
如果命令行参数出于任何原因不可取或不实用,您当然可以在配置文件或数据库表中使用设置

无论您如何操作,您都可以在高吞吐量模式或可恢复诊断模式下运行服务器,并使用最少的重复语法:

try
  case ServerMode of
    smDiagnostic     : repeat
                         try
                           getInput;
                           putOutput;
                         except
                           on e: Exception do .... // etc      
                         end;
                       until FALSE;

    smHighThroughput : repeat
                         getInput;
                         putOutput;
                       until FALSE;
  end;

except
  on e: Exception do .... // etc      
end;
请注意,即使在高吞吐量模式下,上面的示例也捕获有关导致服务器终止的任何异常的信息。诊断模式记录所有异常,但尝试保持服务器运行

然后,如果需要诊断异常不稳定的服务器,您可以使用启用诊断模式的选项将其默认为高通量模式

说了这么多,我会尝试确定量化尝试的影响…除了在循环上,然后再花很大的精力去设计这种影响

将ApplicationEvents放置在应用程序的中心位置。 实现OneException事件。 删除本地服务器尝试…删除开销除外。 在异常事件中,您可以执行任何操作,包括记录异常。 如果你想在游戏中添加一些特别的东西 异常仍然可以进行本地重试。除了并修改E.消息,然后调用raise。然后,将使用修改后的消息调用全局异常处理程序

将ApplicationEvents放置在应用程序的中心位置。 实现OneException事件。 删除本地服务器尝试…删除开销除外。 在异常事件中,您可以执行任何操作,包括记录异常。

如果您想在异常中添加一些特殊的内容,那么仍然可以进行本地尝试。除了并修改E.消息,然后调用raise。然后,将使用修改后的消息调用全局异常处理程序。

使用try…except块如何给服务器增加大量的执行开销?分析可能引起的问题exceptions@Robert:不使用try.“repeat”循环执行得更快..除了。我忘了有多少了,但这是相当可观的。想象一下你有一个缓冲区溢出错误。现在你可能正在破坏记忆。出错后继续操作可能会导致使用损坏的内存。听起来对我很危险。在这种情况下,我更愿意终止服务器并重新启动它。@WitnessProtectionID44583292,您说输入/输出例程包含数千行代码,但try/except帧将循环速度降低了25%。这意味着大部分时间>>99%,I/O例程什么也不做。对我来说,这似乎是一个轮询场景,应该重构为事件驱动。使用try…except块如何给服务器增加大量的执行开销?分析会引起什么exceptions@Robert:不使用try.“repeat”循环执行得更快..除了。我忘了有多少了,但这是相当可观的。想象一下你有一个缓冲区溢出错误。现在你可能正在破坏记忆。出错后继续操作可能会导致使用损坏的内存。听起来对我很危险。在这种情况下,我更愿意终止服务器并重新启动它。@WitnessProtectionID44583292,您说输入/输出例程包含数千行代码,但try/except帧将循环速度降低了25%。这意味着大部分时间>>99%,I/O例程什么也不做。在我看来,这似乎是一个轮询场景,应该重构为事件驱动。是的,这是在user246408的评论之后实现的双重重复。试着/除了内心的重复会让事情慢很多。使用try/except在内部repeat之外,只要没有异常发生,它的速度就和no try/except一样快。如果出现异常,外部repeat将保持服务器运行。是的。但如果你能测量性能差异,我还是会感到惊讶。try/except inside repeat/till会使循环速度降低25%左右。这似乎与你之前的评论不一致。我仍然相信这比这里介绍的要多。我同意,try/except框架对性能的影响这一事实意味着I/O例程在大多数时间都在轮询数据,而无需做任何事情。是的,这是user246408评论后实现的双重重复。试着/除了内心的重复会让事情慢很多。使用try/except在内部repeat之外,只要没有异常发生,它的速度就和no try/except一样快。如果出现异常,外部repeat将保持服务器运行。是的。但如果你能测量性能差异,我还是会感到惊讶。try/except inside repeat/till会使循环速度降低25%左右。这似乎与你之前的评论不一致。我仍然相信这比这里介绍的要复杂得多。我同意,try/except帧对性能的影响这一事实意味着I/O例程大部分时间都在轮询数据,而无需做任何事情。try/except inside repeat/until会使循环变慢约25%。我很好奇您是如何衡量这一点的。我创建了一个比较案例,发现确实存在差异,但只有13%。这是所有的句法元素,但在加工过程中没有真正的肉。就实际运行时间开销而言,仅在循环内部添加try/except的影响进行测量时,13%的差异实际上仅为0.0003秒。但是,这种开销将是一个绝对经过的时间,因此作为整个循环迭代的一个百分比,当您向循环添加实际工作时,这种开销可能会变得几乎可以忽略不计。我同意David和其他人的观点,如果在您的情况下确实增加了25%,那么问题就不那么清楚了。我也很怀疑是否使用了管理费用的%年龄指标。正如他们在零售业中所说的,你不能把一个百分比存入银行,这里要解释一下。。。手表没有百分率指针。我想知道在需要异常处理的情况下,是否是导致异常的问题以及对异常的处理导致了开销,而不是在没有异常的情况下try/except本身。i、 e.相关性,而不是因果关系。尝试/除了内部重复/直到循环速度减慢25%左右。我很好奇你是如何做到的
我们正在测量这个。我创建了一个比较案例,发现确实存在差异,但只有13%。这是所有的句法元素,但在加工过程中没有真正的肉。就实际运行时间开销而言,仅在循环内部添加try/except的影响进行测量时,13%的差异实际上仅为0.0003秒。但是,这种开销将是一个绝对经过的时间,因此作为整个循环迭代的一个百分比,当您向循环添加实际工作时,这种开销可能会变得几乎可以忽略不计。我同意David和其他人的观点,如果在您的情况下确实增加了25%,那么问题就不那么清楚了。我也很怀疑是否使用了管理费用的%年龄指标。正如他们在零售业中所说的,你不能把一个百分比存入银行,这里要解释一下。。。手表没有百分率指针。我想知道在需要异常处理的情况下,是否是导致异常的问题以及对异常的处理导致了开销,而不是在没有异常的情况下try/except本身。i、 相关性,而不是因果关系。我怀疑这是VCL表单应用程序。您在repeat循环中看到的是主处理循环。OneException基于主VCL消息循环。所以,这里不适用。我怀疑这是一个VCL表单应用程序。您在repeat循环中看到的是主处理循环。OneException基于主VCL消息循环。所以,这里不适用。