Home arrow Support arrow Gurock Software Forum arrow General Discussion arrow Create object TSmartInspect at runtime

Subscribe to forum RSS Forum

Create object TSmartInspect at runtime

New Topic Post Reply

Page: 1

Author Post
acruc
Guest
I want to create the smartinspect object at the run time on one method that is called at fixed interval. For the first execution it is ok , but next execution throw exception.

The code follow the pattern :

try
CreateSmartInspect(connectionTCP, 'DemoServer', SI1, SIMain1);
…. Log the mesage
finally
FreeSmartInspect(SI1);
end;

where

Procedure TDemoServer.CreateSmartInspect(Connection: String; SessionName: String; Var ASI: TSmartInspect; Var ASIMain: TSiSession);
Var retVal: TSmartInspect;
Begin
If ASI <> Nil Then Begin
ASI.Free;
End;

ASI := TSmartInspect.Create(Application.Title);
ASI.Connections := Connection;
ASI.OnError := ExceptionHandler;
ASIMain := ASI.AddSession(SessionName);
ASI.Enabled := true;

End;

Procedure TDemoServer.FreeSmartInspect(Var ASI: TSmartInspect);
Begin
If ASI <> Nil Then Begin
ASI.OnError := Nil;
ASI.Enabled := false;
ASI.Free;
End;


End;


At second execution it is throw AV exception
Note that this error is not raise if I using the default SmartInspect SI object(but I need separate log connection and message pattern)

I used the 2.3.4.7144 version (I think the last available from download)

It is you code bug or the bug is in my square :( ?

Thanks
Aurelian
Administrator
Registered: Sep 2007
Posts: 132
Hello Aurelian,

Thanks for your posting. I tried your code but unfortunately could not reproduce this problem (i.e. it does not throw an AV here). I have a few questions:

At which interval do you call the CreateSmartInspect routine and which component do you use for this (TTimer?)?
In which line does the AV occur?
Do you use the SI1 variable in other threads while freeing/creating the TSmartInspect objects?
Member
Registered: Jun 2008
Posts: 11
Thanks for you response, I put all the code here
The form contain 2 buttons



Unit SmartInspectAdv;

Interface

Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,
SmartInspect, SiAuto;

Type
TFrmSIAdv = Class(TForm)
Panel1: TPanel;
Memo1: TMemo;
btn2SI: TButton;
btnSIMain: TButton;
Procedure btn2SIClick(Sender: TObject);
Procedure btnSIMainClick(Sender: TObject);
Private
{ Private declarations }
Public
{ Public declarations }
Procedure ExceptionHandler(ASender: TSmartInspect; AException: Exception);
Procedure CreateSmartInspect(Connection: String; SessionName: String; Var ASI: TSmartInspect; Var ASIMain: TSiSession);
Procedure FreeSmartInspect(Var ASI: TSmartInspect);

End;

Var
FrmSIAdv: TFrmSIAdv;

Implementation
{$R *.dfm}


Var SI1, SI2: TSmartInspect;
SIMain1, SIMain2: TSiSession;
Const
connectionTCP: String = 'tcp(host="localhost")';
connectionTCP_FILE: String = 'file(filename="log.sil", append=true),tcp(host="localhost")';

TEN = 10;

//ExceptionHandler display error on Memo
Procedure TFrmSIAdv.ExceptionHandler(ASender: TSmartInspect; AException: Exception);
Begin
Memo1.Lines.Add(AException.Message);
Memo1.Lines.Add('Error Receive with ...' + TSmartInspect(ASender).Version);
End;

Procedure TFrmSIAdv.CreateSmartInspect(Connection: String; SessionName: String; Var ASI: TSmartInspect; Var ASIMain: TSiSession);
Begin
If ASI <> Nil Then Begin
ASI.Free;
End;

ASI := TSmartInspect.Create(Application.Title);
ASI.Connections := Connection;
ASI.OnError := ExceptionHandler;
ASIMain := ASI.AddSession(SessionName);
ASI.Enabled := true;

End;

Procedure TFrmSIAdv.FreeSmartInspect(Var ASI: TSmartInspect);
Begin
If ASI <> Nil Then Begin
ASI.OnError := Nil;
ASI.Enabled := false;
ASI.Free;
End;


End;

Procedure TFrmSIAdv.btn2SIClick(Sender: TObject);
Var i, j: integer;
Begin
// Create 2 TSmartInspect Object that send date to the same TCP Connection
CreateSmartInspect(connectionTCP, 'Main01', SI1, SIMain1);
CreateSmartInspect(connectionTCP, 'Main02', SI2, SIMain2);

// CreateSmartInspect(connectionTCP_FILE,SI1,SIMain1);
// CreateSmartInspect(connectionTCP_FILE,SI2,SIMain2);


SIMain1.Color := clCream;
SIMain2.Color := clYellow;

SiMain1.EnterMethod(Self, 'btn2SIClick');
SiMain2.EnterMethod(Self, 'btn2SIClick');
Try

For i := 1 To TEN Do
Begin
Memo1.Lines.Add('Step ' + intToStr(i));
For j := 1 To TEN Do
Begin
SIMain1.LogDebug('Main_1 %4d %4d', [i, j]);
SIMain1.WatchInteger('Internal_1 I ', i);
SIMain1.WatchInteger('Internal_1 J ', j);
Sleep(10);
SIMain2.LogDebug('Main_2 %4d %4d', [i, j]);
SIMain1.WatchInteger('Internal_2 I ', i);
SIMain1.WatchInteger('Internal_2 J ', j);

Sleep(10);

End;
SIMain.LogSeparator;

End;
Finally
SiMain1.LeaveMethod(Self, 'btn2SIClick');
SiMain2.LeaveMethod(Self, 'btn2SIClick');
End;

//Free the connection
FreeSmartInspect(SI1);
FreeSmartInspect(SI2);

End;

//use SI and SIMain
Procedure TFrmSIAdv.btnSIMainClick(Sender: TObject);
Var i, j: integer;
Begin
SIMain.Color := clTeal;

For i := 1 To TEN Do
Begin
Memo1.Lines.Add('Step ' + intToStr(i));
For j := 1 To TEN Do
Begin
SIMain.LogDebug('Main_1 %4d %4d', [i, j]);

End;
End;

End;



End.



If click twice on the btn2SI button you see the AV.
Administrator
Registered: Sep 2007
Posts: 132
I was able to reproduce the problem. The problem is that you call Free twice on the same TSmartInspect object, once in FreeSmartInspect on the first run and then the second time in CreateSmartInspect. This then results in the Access Violation.

In most cases, it's a good idea to use FreeAndNil instead of the Free method directly because this also sets the Pointer/Reference to nil and thus avoids the 'dangling pointer' problem (a reference to an object which is no longer valid). So, one fix would be to replace the ASI.Free calls with FreeAndNil(ASI). It works fine then.
« Last edit by Tobias Gurock on Sun Jun 15, 2008 1:13 pm. »
Member
Registered: Jun 2008
Posts: 11
Yap, you right,

Thanks
Aurelian

New Topic Post Reply

Page: 1