views:

394

answers:

3

I often make small methods to assist debugging, which aren't used in the actual program. Typically most of my classes has an AsString-method which I add to the watches. I know Delphi 2010 has visualizers, but I'm still on 2007.

Consider this example:

program Project1;

{$APPTYPE CONSOLE}

uses SysUtils;

type
  TMyClass = class
    F : integer;
    function AsString : string;
  end;

function TMyClass.AsString: string;
begin
  Result := 'Test: '+IntToStr(F);
end;

function SomeTest(aMC : TMyClass) : boolean;
begin
  //I want to be able to watch aMC.AsString while debugging this complex routine!
  Result := aMC.F > 100; 
end;

var
  X : TMyClass;

begin
  X := TMyClass.Create;
  try
    X.F := 100;
    if SomeTest(X)
      then writeln('OK')
      else writeln('Fail');
  finally
    X.Free;
  end;
  readln;
end.

If I add X.AsString as a watch, I just get "Function to be called, TMyClass.AsString, was eliminated by linker".

How do I force the linker to include it? My usual trick is to use the method somewhere in the program, but isn't there a more elegant way to do it?

ANSWER: GJ provided the best way to do it.

initialization
  exit;
  TMyClass(nil).AsString;

end.
+5  A: 

You can make function published.

  TMyClass = class
    F : integer;
  published
    function AsString : string;
  end;

And switch on in 'Watch Properties' 'Allow function calls'

GJ
Great! I didn't know that published methods worked that way. Do you have a tip for unit functions also?
Svein Bringsli
You can also put "published" like:{$IFDEF DEBUG}published {$ENDIF}
GJ
A: 

Maybe it works to call them in some initialization section, guarded by {IFDEF DEBUG} or {IFOPT D+}.

Ulrich Gerhardt
Yes, this would work, but I want to find a way that _doesn't_ require me to actually call the function somewhere.
Svein Bringsli
Of course that would be nice to have. But at least it's a workaround that doesn't burden the release version. (Which GJ's published trick would, BTW. :-))
Ulrich Gerhardt
+6  A: 

sveinbringsli ask: "Do you have a tip for unit functions also?"

Delphi compiler is smart... So you can do something like...

unit UnitA;

interface

{$DEFINE DEBUG}

function AsString: string;

implementation

function AsString: string;
begin
  Result := 'Test: ';
end;

{$IFDEF DEBUG}
initialization
  exit;
  AsString;
{$ENDIF}
end.
GJ
+1. That's what I usually do. Place it in an initialization block so it won't get linked out.
Mason Wheeler
I was battling with myself over which answer I should accept - this one or your other answer with the "published trick". I chose this one because it will not affect the release version.
Svein Bringsli
Yes, and if your function need some parameters like variables, just write in initialization section: "if @AsString = nil then;" instead puting parameters in.
GJ
GJ, does your comment suggestion really work? I might expect an "expression always evaluates to false" hint, and then the compiler could remove the expression.
Rob Kennedy
@Rob Kennedy: in my test case uder D2007 works good.Us I understand compiler at first insert the code of function and then test the address. You can also set Breakpoint to this line. Check it.
GJ
@Rob Kennedy: I also use exit sentence before this line. So this line will never be executed.
GJ