12

The Delphi documentation states :

Never raise an EInvalidPointer exception directly. EInvalidPointer is raised internally by the memory manager.

I'm writing a custom base class as an alternative to TInterfacedObject, following the RTL implementation as closely as possible, and see, by example, that TInterfacedObject in the RTL implements BeforeDestruction as:

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

Where Error(reInvalidPtr) raises EInvalidPointer through a variety of unit-scoped methods local to the RTL.

If I'm writing my own class, how should I implement BeforeDestruction? Why not do this? :

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

Is there something special with the global InvalidPointer exception object declared in SysUtils? If this is a bad idea, would it be sensible to simply raise a custom exception here?

J...
  • 30,968
  • 6
  • 66
  • 143
  • 1
    I think `System.Error(reInvalidPtr);` is perfectly respectable here. Why not simply do that. So far as I can tell, that is the correct way to signal an invalid pointer exception. If it's good enough for the RTL why shouldn't you do the exact same. – David Heffernan Dec 20 '16 at 18:36
  • @DavidHeffernan To be honest, I didn't even try it. There is no forward declaration of `Error` (it's buried in `implementation`) so I assumed it just wouldn't compile. Silly me. – J... Dec 20 '16 at 18:43
  • Agreed, absolutely. I was initially fooled by the `ERROR` const in the `Windows` unit hiding this so I assumed it was just inaccessible - not finding a forward declaration just seemed to confirm it. Should have just tried it anyways, I guess! – J... Dec 20 '16 at 18:47

2 Answers2

9

Complementary to David's answer; what's special about InvalidPointer, which is used to raise an EInvalidPointer, together with OutOfMemory <-> EOutOfMemory is explained in more detail in the documentation topic for their ascendant EHeapException:

EHeapException is the exception class for errors related to heap-allocated memory.

EHeapException's descendants—EOutOfMemory and EInvalidPointer—are used to handle failed allocations of dynamic memory and invalid pointer operations.

Note: Memory for these exceptions is pre-allocated whenever an application starts and remains allocated as long as the application is running. Never raise EHeapException or its descendants directly.

Which amounts to I guess is, it may not be safe to allocate memory for creating these errors once you have problems with memory: for lack of it or possible corruption...

Community
  • 1
  • 1
Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
6

Sidestepping the original question, you can avoid asking it simply by using the same code as the runtime:

System.Error(reInvalidPtr);
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490