为什么不引发EInvalidPointer异常?

12

Delphi的文档声明

不要直接触发EInvalidPointer异常。 EInvalidPointer由内存管理器内部引发。

我正在编写一个自定义基类作为TInterfacedObject的替代品,并尽可能地按照 RTL 实现,通过示例,我看到 RTL 中的 TInterfacedObjectBeforeDestruction 实现为:

procedure TInterfacedObject.BeforeDestruction;
begin
  if RefCount <> 0 then
    Error(reInvalidPtr);  
end;

Error(reInvalidPtr)会通过一系列局部于RTL的单元范围方法引发EInvalidPointer异常。

如果我要编写自己的类,应该如何实现BeforeDestruction方法?为什么不要这样做?:

procedure TMyInterfacedObject.BeforeDestruction;
begin
  if RefCount <> 0 then
    raise EInvalidPointer.CreateRes(@SInvalidPointer) at ReturnAddress;
end;

全局InvalidPointer异常对象在SysUtils中声明时是否具有特殊性?如果这是个不好的想法,那么在此处引发自定义异常是否明智?


1
我认为在这里使用 System.Error(reInvalidPtr); 是完全可以的。为什么不直接这样做呢?据我所知,这是发出无效指针异常信号的正确方式。如果这对 RTL 足够好,为什么你不能完全一样呢? - David Heffernan
@DavidHeffernan 老实说,我甚至都没试过。因为Error没有前向声明(它被埋在implementation中),所以我认为它根本无法编译。我真是太傻了。 - J...
同意,完全正确。一开始我被Windows单元中的ERROR常量所迷惑,认为它是不可访问的,而找不到前向声明似乎也证实了这一点。我应该试一下的,我猜! - J...
2个回答

9

作为David's answer的补充,InvalidPointer是用于引发EInvalidPointer异常的特殊内容,与OutOfMemory <-> EOutOfMemory一起使用,更详细的解释在它们的祖先EHeapException的文档主题中:

EHeapException是与堆分配内存相关的错误的异常类。

EHeapException的子类——EOutOfMemoryEInvalidPointer,用于处理动态内存分配失败和无效指针操作。

注意:这些异常的内存在应用程序启动时预分配,并在应用程序运行期间保持分配状态。永远不要直接引发EHeapException或其子类异常。

我想说的是,一旦你遇到内存问题:缺乏内存或可能出现损坏,为创建这些错误分配内存可能不安全...


那很有道理。 - J...

6
绕开原问题,只需使用与运行时相同的代码即可避免提出该问题:
System.Error(reInvalidPtr);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接