使用asm代码创建Access-Violation以进行测试的优势?

时间:2016-08-01 17:38:41

标签: delphi

我们最近开始使用madExcept而不是ExcMagic作为我们的异常处理程序。 我们还在开发64位版本的应用程序,因此希望尽可能消除asm代码的使用。

ExcMagic有这个程序来创建访问冲突以进行测试。

procedure CreateAccessViolation
begin
  asm
    mov eax,11111111h
    mov ebx,22222222h
    mov ecx,33333333h
    mov edx,44444444h
    inc dword ptr [eax]
  end;
end;

使用该代码是否有任何优势,而不仅仅是编写

raise EAccessViolation.Create('Just testing...');

ExcMagic开发人员必须使用它。

谢谢!

2 个答案:

答案 0 :(得分:3)

访问冲突列出了访问过的地址(在本例中为$11111111) 因为它的这种不寻常的地址会突然出现。

如果查看堆栈跟踪,它通常会列出崩溃时寄存器的值,因为它们的异常值会再次出现红色标记。

我的猜测是代码库通过检查幻数来使用它来区分自己的异常和其他异常。

然而,在我看来,这是一种伪造自定义异常的非常愚蠢的方法 一个更有用的方法是创建自己的异常类并提高它。

type
  EMadException = class(Exception)
    //custom fields, constructors, properties, etc can be added
  end;

  begin
    raise EMadException.Create('info');
  end; 

在错误对话框中,它会清楚地说明例外的名称以及您提供的任何信息 这也使得区分您的例外与其他人之间的关系变得微不足道了:

try
  DoSomething
except 
  on E: EMadException do ShowMessage('it''s mine');
  else ShowMessage('not mine');
end;

答案 1 :(得分:3)

操作系统级别的异常不是对象。它们是可能带有其他上下文数据的数值。当您尝试读取或写入无效地址时,您将获得异常代码Exception_Access_Violation,其中包含提供尝试操作和地址的上下文,但是当您使用raise保留字时,您将获得异常代码{{1}用connect给出一个Delphi对象引用。 (你知道你可以抛出任何对象,而不仅仅是cDelphiException的后代吗?)

在Delphi的说法中,操作系统级别的异常称为运行时错误

SysUtils单元中的代码会将由汇编代码创建的访问冲突运行时错误转换为Exception Delphi异常。这样可以很容易地捕获Delphi的EAccessViolation - try语法。

如果调用堆栈上有非Delphi代码(或者甚至可能是不使用SysUtils的Delphi代码),它可能无法识别except异常代码,即使它发生了,也可能无法区分一个Delphi对象类型。另一方面,cDelphiException在所有Windows代码中都是已知的。

如果您想测试来自访问冲突的行为,那么最好是实际违反访问权限。这就是汇编代码试图做的事情。 (它是否成功是一个单独的问题。)如果你想测试捕获的Delphi对象,那么抛出你想要的任何对象,包括Exception_Access_Violation的实例。