在浏览System.Zip(Delphi XE2)以查看其工作原理时,我发现了这个功能:
procedure VerifyWrite(Stream: TStream; var Buffer; Count: Integer);
begin
if Stream.Write(Buffer, Count) <> Count then
raise EZipException.CreateRes(@SZipErrorWrite) at ReturnAddress;
end;
Run Code Online (Sandbox Code Playgroud)
at ReturnAddress
这是让我困惑的部分.
我不知道这at
是一个有效的关键字(语法高亮显示器似乎也没有识别它).
根据IDE声明它System.ReturnAddress
,但我只能在(asm)代码中的某处找到它声明为标签procedure _HandleAnyException;
.但系统单元充满了对它的引用.
所以我想知道的是:
ReturnAddress
?Raise Exception.Create ... at ReturnAddress
做什么的?如果你可以给出一个真实世界的例子,说明这将是一个有用的结构,或者你可以建议不要使用它.
Ken*_*ite 20
ReturnAddress
是VerifyWrite
完成后将返回的地址.
Raise Exception.Create... at ReturnAddress
表示当显示异常对话框时,它将指示异常的地址为ReturnAddress
.换句话说,将读取异常消息Exception <whatever> raised at <ReturnAddress>: <Exception Message>
.
以下是Delphi 7帮助文件的摘录.它与在线版本几乎相同.
要引发异常对象,请使用带有raise语句的异常类的实例.例如,
Run Code Online (Sandbox Code Playgroud)raise EMathError.Create;
一般来说,加薪声明的形式是
Run Code Online (Sandbox Code Playgroud)raise object at address
其中object和at地址都是可选的; 请参阅重新提出例外情况.指定地址时,它可以是任何求值为指针类型的表达式,但通常是指向过程或函数的指针.例如:
Run Code Online (Sandbox Code Playgroud)raise Exception.Create('Missing parameter') at @MyFunction;
使用此选项可以从堆栈中的早期点引发异常,而不是实际发生错误的异常.
请特别注意最后一句.它的使用非常具体at <address>
.
ReturnAddr
这不是以前Delphi版本的谜题.考虑下一个测试(Delphi XE):
procedure RaiseTest1;
procedure RaiseException(ReturnAddr: Pointer);
begin
raise Exception.Create('OOPS!') at ReturnAddr;
end;
asm
POP EAX
JMP RaiseException
end;
procedure RaiseTest2;
begin
raise Exception.Create('OOPS!');
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
RaiseTest1;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
RaiseTest2;
end;
Run Code Online (Sandbox Code Playgroud)
如果您在调试器下按下Button3并在异常消息框中按'Break',调试器将停止
procedure TForm1.Button3Click(Sender: TObject);
begin
RaiseTest1; // <-- here
end;
Run Code Online (Sandbox Code Playgroud)
如果您按下Button4,调试器将停止
procedure RaiseTest2;
begin
raise Exception.Create('OOPS!'); // <-- here
end;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,RaiseTest1修改了默认的异常堆栈帧,并使调试更加简单,因为RaiseTest1(2)过程的唯一目的是引发异常.
我想在XE2中发生了一些变化,因此ReturnAddr
语法得到了简化.