delphi - 为什么重新引发 Exception 对象时,其更改会丢失?

标签 delphi exception

我确信这曾经对我有用,而且我已经在网上看到了它(Jolyon Smith 和 David Moorhouse)。刚刚在 D2007 和 XE2 试用版中的简单程序中尝试过,它不会保留修改后的消息。一旦发生“引发”,消息就会恢复到原始异常。

我错过了什么明显的东西?另一种方法是“引发 Exception.Create(...)”,但我只想将原始异常传播到链上,仅在每个异常 block 上标记附加信息。

var a: Integer;
begin
  try
    a := 0;
    Label1.Caption := IntToStr(100 div a);
  except
    on e: Exception do
    begin
      e.Message := 'Extra Info Plus the original : ' + e.Message;
      raise;
    end;
  end;
end;

最佳答案

好吧,吹我吧!这看起来太错误了,我不得不亲自尝试一下,你是绝对正确的!我已经将范围缩小到这样一个事实:这是一个操作系统异常(除以零),它是由操作系统本身生成的,而不是由 Delphi 生成的。如果您尝试自己引发 EIntError,您会得到预期的行为,而不是您在上面看到的行为。请注意,只要您自己引发异常,就会出现预期的行为。

更新:在 System.pas 单元中,重新引发异常时会调用以下代码:

{ Destroy any objects created for non-delphi exceptions }

MOV     EAX,[EDX].TRaiseFrame.ExceptionRecord
AND     [EAX].TExceptionRecord.ExceptionFlags,NOT cUnwinding
CMP     [EAX].TExceptionRecord.ExceptionCode,cDelphiException
JE      @@delphiException
MOV     EAX,[EDX].TRaiseFrame.ExceptObject
CALL    TObject.Free
CALL    NotifyReRaise

因此,如果异常不是 Delphi 异常(在本例中为操作系统异常),则释放(修改后的)“Delphi”异常并重新引发原始异常,从而丢弃对异常所做的任何更改。案件已结!

更新2:(无法控制自己)。您可以使用以下代码重现此内容:

type
  TThreadNameInfo = record
    InfoType: LongWord;  // must be $00001000
    NamePtr: PAnsiChar;  // pointer to message (in user address space)
    ThreadId: LongWord;  // thread id ($ffffffff indicates caller thread)
    Flags: LongWord;     // reserved for future use, must be zero
  end;

var
  lThreadNameInfo: TThreadNameInfo;

  with lThreadNameInfo do begin
    InfoType := $00001000;
    NamePtr := PAnsiChar(AnsiString('Division by zero'));
    ThreadId := $ffffffff;
    Flags := $00000000;
  end;
  RaiseException($C0000094, 0, sizeof(lThreadNameInfo) div sizeof(LongWord), @lThreadNameInfo);

玩得开心!

关于delphi - 为什么重新引发 Exception 对象时,其更改会丢失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7347025/

相关文章:

delphi - TEdit onclick 全选?

c++ - 在构造函数 C++ 中处理 Try-catch block

python - 遇到第一个异常时,如何使scrapy crawl 中断并退出?

php - 在 PHP 中,什么是 `ClosedGeneratorException` ?

delphi - delphi语言获取微秒时间

delphi - 如何在 TDBGrid 中显示富文本?

Delphi TRichEdit.Perform( EM_FORMATRANGE, 0,Longint(@fmtRange));

delphi - 如何在 xmldoc 注释中添加换行符

c# - AggregateException - AggregateException.Flatten().InnerException 代表什么?

c# - HRESULT 异常 : 0xC00D36B4