我确信这是为我工作,我已经在网上看到了(Jolyon Smith和David Moorhouse)。刚刚在D2007和XE2试用版中的一个简单的程序中尝试过,它不保留修改的消息。一旦发生“升级”,该消息将恢复原始异常。
我迷失了多少明显的事情?另一种方法是“提高Exception.Create(…)”,但是我只想将原始异常备份到链上,只有在每个异常块处标记了附加信息。
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异常(在这种情况下是一个OS异常),那么(修改的)“Delphi”异常将被释放,原始异常被重新引发,从而抛出对异常所做的任何更改。案件关闭!
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,sizeof(lThreadNameInfo) div sizeof(LongWord),@lThreadNameInfo);
玩的开心!