适当的灾难性错误处理

时间:2013-01-20 05:50:09

标签: delphi error-handling delphi-2006 delphi-3

有一些我一直在努力的东西,我真的没有用Delphi程序解决,并想知道是否有人可以指导我。正如主题所说,你如何做正确的灾难性错误处理?例如:

// is file necessary for the program present?
if not FileExists(FilePath1) then
   begin
     raise Exception.Create(FilePath1 + ' does not exist and is required for this program to function.');
   // I obviously need to do something here to make the program QUIT and not have
   // any more code run.

     Application.Terminate;
     Abort;
   end;

我也可以在那里使用异常单元并抛出异常,但程序会像以前一样继续。我过去曾经使用过停止呼叫,但它似乎没有进行任何清理等等,所以我最终制定了一个大程序,通过近距离和免费调用我所做的一切就是为了确保(即使那时我我不确定任何幕后的东西。

那么处理这类事情的正确方法是什么?

编辑:为了澄清,我想知道如何让程序执行它需要做的清理,然后立即退出而不执行任何其他代码。

4 个答案:

答案 0 :(得分:6)

要执行异常终止,请调用Halt()传递退出代码。

if CatastropicErrorDetected then
begin
  ... show error message
  Halt(1);
end;

在Windows上,这会导致调用TerminateProcess并在那时停止执行。

您注意到没有执行清理,通常这就是您想要的。由于您在应用程序启动时执行此检查,因此无需清理任何内容。

答案 1 :(得分:2)

恕我直言,唯一干净的方法是在应用程序运行之前检查“致命条件”。

program Project2;

uses
  Forms,Dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  ReportMemoryLeaksOnShutDown := true;
  Application.Initialize;
  if True then // your condition here
    begin
      MessageDLG('Fatal Error',mtError,[mbok],0);
    end
  else
    begin
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end;
end.

任何其他方法都会产生副作用

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    FSL:TStringList;
  public
   Destructor Destroy;override;
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

destructor TForm1.Destroy;
begin
  FreeAndNil(FSL);
  Showmessage('Will never be seen with Application.Terminate + HALT');
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
const
  Testing=0; // try 1 and 2 too
begin

   FSL:=TStringList.Create;
   Try
      raise Exception.Create('Terminating now');
   except
     case Testing of
         0: begin
             // exception object will not be freed other code will be prevented, Form won't be shown
             Application.Terminate;
             HALT;
            end;
         1: begin
             // exception object will not be freed Form won't be shown
             HALT;
            end;
         2: begin
             // clean but Form will be shown
             Application.Terminate;
            end;

     end;
   end;

end;

end.

答案 2 :(得分:1)

您可以通过调用Application.Terminate来指示应用程序全局对象终止程序。

  

调用Terminate以编程方式结束应用程序。通过调用Terminate而不是释放应用程序对象,允许应用程序以有序的方式关闭

     

终止调用Windows API PostQuitMessage函数以执行应用程序的有序关闭。终止不是立竿见影的。

由于调用可以在堆栈中更深入地发生,因此您也可以raise an Exception,并且编写程序以使其无法处理,以便让执行到达主应用程序循环并且默认异常处理程序捕获它。

这样,您可以有效地阻止在您的应用程序中运行更多代码。

在代码中它可能如下所示:

if not FileExists(FilePath1) then
  begin
    MessageDlg(FilePath1 + ' does not exist and is required for this program to function.',
               mtWarning, [mbOK], 0);

    Application.Terminate;
    Abort;  //raising a EAbort just as an example
  end;

根据调用此代码的位置,我建议您不要直接显示消息,而是使用消息引发异常并让应用程序对象默认HandleException方法为您显示消息:

if not FileExists(FilePath1) then
  begin
    Application.Terminate;
    raise EMyFatalException.Create(FilePath1 
      + ' does not exist and is required for this program to function.');
  end;

对我来说这看起来更自然。 EMyFatalException是一个假设的异常类,您可以声明并且永远不会在您的except子句中处理。

答案 3 :(得分:1)

您可以编写自己的Application.OnException处理程序,例如:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure HandleException(Sender: TObject; E: Exception);
  end;

var
  Form1: TForm1;

type
  EMyFatalError = class(Exception);

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.OnException:= HandleException;
  raise EMyFatalError.Create('OOPS!');
end;

procedure TForm1.HandleException(Sender: TObject; E: Exception);
begin
  Application.ShowException(E);
  if E is EMyFatalError then
    Application.Terminate;
end;

end.