Root > How to... > ...retrieve object instance from a call stack?

...retrieve object instance from a call stack?

Previous pageReturn to chapter overviewNext page   

Sometimes you may want to know what object's method was called. For example, you can see TObject.Destroy call in the call stack, but this information gives you the class (TObject) and not the instance/object.

 

Generally, it is not possible to extract Self (or any other argument) from the call stack alone. For example, Self may be passed in the EAX CPU register, but immediately saved in some other register (or the CPU stack) for later use (to free the EAX register for an upcoming code).

 

Therefore, if you need to know instance/object or any other argument to a function/method - you have to use logging. The idea is that you save Self and other arguments to a log file. That log file can be attached to a bug report later.

 

You can use the following for logging:

Your own logger

 

Remember the following when using logging:

TObject has the ToString method (in not too old IDEs) - which you can use to convert an object/instance into a string;
You can overload the ToString method in your own objects - to improve logging detalization;
EurekaLog has __MODULE__, __UNIT__, __FILE__, __FUNCTION__, and __LINE__ functions (EDebugInfo unit);
RTL has the ReturnAddress function (in not too old IDEs);
EurekaLog has the TEurekaStackList.Caller function (available in all IDEs, ECallStack unit).

 

So, your code may look like this (if you are using EurekaLog as your logging solution):

 

uses
  ELogging,   // for logging functions
  EDebugInfo; // for debug information functions
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  ELogEnter(Self, __FUNCTION__).P('Sender', Sender).C;
 
  // Your actual code goes here
end;

 

The actual log file will be attached to bug reports automatically.

 

Or, if you are using your own logging, you may do something like this:

 

 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Log(Sender);
 
  // Your actual code goes here
end;

 

where Log is:

 

uses
  ECallStack, // for TEurekaStackList.Caller
  EDebugInfo; // for debug information functions
 
procedure Log(const AMessage: String); overload;
begin

  // ...
  // - your code here to save AMessage into your own log file

  // ...
  OutputDebugString(PChar(AMessage)); // only as an example for testing
end;
 
procedure Log(Sender: TObject); overload;
var
  Caller: Pointer;
  CallerStr: String;
begin
  Caller := TEurekaStackList.Caller;
  CallerStr := GetLocationInfoStr(Caller);
  Log(Format('%s (%s)', [CallerStr, Sender.ToString]));
end;

 

This code will output something like:

 

(0046166B){Project1.exe} [0058166B] Unit1.TForm1.Button1Click (Line 60, "Unit1.pas") + $3 (Form1: TForm1)

 

Alternatively, if you are using an old IDE (which does not have the ToString method) or you can enrich the ToString method:

 

function ObjToStr(const AObj: TObject): String;
begin
  if AObj is TStrings then
    Result := StringReplace(TStrings(AObj).Text, sLineBreak, ' ', [rfReplaceAll])
  else
  // ... 

  // - add other useful classes here 

  // ...
  if AObj is TComponent then
    Result := Format('%s: %s', [TComponent(AObj).Name, AObj.ClassName])
  else

    // for modern IDEs:

    Result := AObj.ToString; 

    // for older IDEs:
    Result := Format('%s: %s', [IntToHex(NativeUInt(AObj), SizeOf(Pointer) * 2), AObj.ClassName]);
end;

 

procedure Log(Sender: TObject); overload;
  // ...
begin
  // ...
  Log(Format('%s (%s)', [CallerStr, ObjToStr(Sender)]));  // - changed
end;

 

 

See also:




Send feedback... Build date: 2024-12-19
Last edited: 2024-06-03
PRIVACY STATEMENT
The documentation team uses the feedback submitted to improve the EurekaLog documentation. We do not use your e-mail address for any other purpose. We will remove your e-mail address from our system after the issue you are reporting has been resolved. While we are working to resolve this issue, we may send you an e-mail message to request more information about your feedback. After the issues have been addressed, we may send you an email message to let you know that your feedback has been addressed.


Permanent link to this article: https://www.eurekalog.com/help/eurekalog/how_to_retrieve_object_instance.php