2

Imagine I have a class: TCantBeDestroyed

Some one knows how to create a kind of instance that can't be destroyed in both cases, directly: CantBeDestroyed.Free; CantBeDestroyed.Destroy;

And can't be destroyed by cast: TObject(CantBeDestroyed).Free; TObject(CantBeDestroyed).Destroy;

Tks.

Rodrigo Farias Rezino
  • 2,687
  • 3
  • 33
  • 60
  • 3
    What if the process is killed? What do you really want to achieve? – Andreas Rejbrand Apr 12 '11 at 19:00
  • I want to protect my singletons from programmers. :p – Rodrigo Farias Rezino Apr 12 '11 at 19:27
  • 3
    @SaCi: Why not just raise an `EStupidProgrammer` in the destructor? – Andreas Rejbrand Apr 12 '11 at 19:29
  • Another way to do this is to avoid letting anyone have access to the singleton instance and hiding it behind class methods. – David Heffernan Apr 12 '11 at 19:29
  • 'Cause it doesn't avoid my customer to get angry and only the destructor isn't the only way to free it. My singleton return an object that can be manipulated any way, but it can't be freed. – Rodrigo Farias Rezino Apr 12 '11 at 19:30
  • 3
    @SaCi well really you'd raise `EDoNotDestroyThisSingleton` and your customer would be fine. Arguably that's better than pretending to free and object but not doing so. That approach is likely to lead to confusion. So long as you tell your customer what the rules are I think it unlikely they will have a problem with refraining to free the singleton. – David Heffernan Apr 12 '11 at 19:41
  • I did this way, 'cause I'm with a very specific case that I must solve immediately and I could not find where is the free in code, now that it isn't causing problem on my customers I'll look for the reason of the problem to change the structure correctly. – Rodrigo Farias Rezino Apr 12 '11 at 19:55
  • @Andreas, @David - Raising an exception in the destructor will put [this](http://stackoverflow.com/questions/5581898/extract-nested-try-finally-blocks/5582734#5582734) or [this](http://stackoverflow.com/questions/398137/what-is-the-best-way-to-do-nested-try-and-finally-statement-in-delphi/398161#398161) kind of constructs in risk, which is seen as an alternative for nested try-finally blocks. Well, I don't like those anyway for exactly this reason, but it seems to be popular.. – Sertac Akyuz Apr 12 '11 at 22:12
  • 1
    @sertac the point is that the exception signals that the programmer has made an error and must correct it so it doesn't really matter if it provokes a leak. The code needs to be fixed asap. – David Heffernan Apr 13 '11 at 07:17

1 Answers1

5

You can't stop anyone calling a destructor or Free, but you can make sure that doing so has no effect:

type
  TCannotBeDestroyed = class
  public 
    destructor Destroy; override;
    procedure BeforeDestruction; override;
    procedure FreeInstance; override;
  end;

destructor TCannotBeDestroyed.Destroy;
begin
  //don't call inherited
end;

procedure TCannotBeDestroyed.BeforeDestruction;
begin
  //don't call inherited
end;

procedure TCannotBeDestroyed.FreeInstance;
begin
  //don't call inherited
end;

I can't imagine why you would want to do this though!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Tks too much, I didn't know about FreeInstance. – Rodrigo Farias Rezino Apr 12 '11 at 19:21
  • 9
    Look, a guaranteed memory leak. :-) – Warren P Apr 12 '11 at 21:08
  • 2
    @Warren, if the object is *supposed* to live for the life of the application it's not a leak. – Cosmin Prund Apr 13 '11 at 08:13
  • With some tools, you can register an expected memory leak. But with some tools, you can't, and even when you can, having an object not finalize itself, even in the finalization section of its own unit, causes a bit of problems for troubleshooting other heap problems. I have a zero leaked memory design rule, even "supposed to leak" is not a good enough reason, to me. – Warren P Apr 13 '11 at 15:17