Page 1 of 1
Memory Leak at DriverManager.GetConnection
Posted: 18.05.2011, 18:52
by JavaPauloMG
Hi Friends,
I have a trouble when i user this statement
"fConnection := DriverManager.GetConnection('zdbc:' + protocol + ':' + '//' + hostname + '/' + database + '?username=' + user + ';password=' + password);"
when i finalize program, the eurekalog, show me a error, the object still in memory, i try many ways to destroy, this object, but for example i use
"freeandnil(fConnection)"
The complier give a acessvilolation, i don't know what i can do to solve this problem... somebody can help me?
Thanks.
P.S: Sorry for my bad english, i'm from Brazil.
Posted: 18.05.2011, 19:26
by Dali
What I see is a call to inherited at the beginning of the destructor. Maybe putting that call at the end will solve your issue.
Posted: 18.05.2011, 19:51
by JavaPauloMG
I modify, but the error persist, i search and see the zdbc api, as based in interfaces, but the destroy don't work in interfaced objects, but i dont found the best way to free this memory, and when i work for some time the O.S have more slow, and the memory used has up.
But thanks my friend for the awser...
Posted: 18.05.2011, 23:56
by trupka
JavaPauloMG,
can you create some example so I can reproduce the problem?
I've been using Zeos with EL and FastMM for some time and never encountered
anything similar...
Posted: 20.05.2011, 13:56
by JavaPauloMG
Hi my friend, this is de code, when i destroy de object using the command "freeandnil", the system give a error, if somebody can help me, thanks to all.
Code: Select all
{*
@author João Paulo da Silva Simões
@version 0.1 - 2011/04/27
}
unit EntityManagerFirebird;
interface
uses
DpaEntity, EntityManager, DpaField, ZConnection, ZDbcIntfs, Dialogs;
type
TEntityManagerFirebird = class(TEntityManager)
private
{ Private declarations }
{*
}
fConnection : IZConnection;
{*
}
function getSelectPreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getSelectKeyFieldsPreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getInsertPreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getUpdatePreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getDeletePreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getFields(dpaFieldArray : TDpaFieldArray) : String;
{*
}
function getFieldsParams(dpaFieldArray : TDpaFieldArray) : String;
{*
}
function getFieldsParamsAnd(dpaFieldArray : TDpaFieldArray) : String;
{*
}
procedure setParamsPreparedStatement(var preparedStatement : IZPreparedStatement; dpaFieldArrays : array of TDpaFieldArray); overload;
protected
{ Protected declarations }
public
{ Public declarations }
{*
}
constructor create(protocol : String; hostname : String; database : String; user : String; password : String; dialect : String);
{*
}
destructor destroy(); override;
{*
}
procedure close(); override;
{*
}
procedure beginTransaction(); override;
{*
}
procedure commitTransaction(); override;
{*
}
procedure rollbackTransaction(); override;
{*
}
procedure persist(entity : TDpaEntity); override;
{*
}
procedure remove(entity : TDpaEntity); override;
{*
}
function find(entity : TDpaEntity) : TDpaEntity; override;
published
{ Published declarations }
end;
implementation
uses SysUtils, StrUtils;
{ TEntityManagerFirebird }
constructor TEntityManagerFirebird.create(protocol : String; hostname : String; database : String; user : String; password : String; dialect : String);
begin
fConnection := DriverManager.GetConnection('zdbc:' + protocol + ':' + '//' + hostname + '/' + database + '?username=' + user + ';password=' + password);
fConnection.SetAutoCommit(True);
fConnection.SetTransactionIsolation(tiReadCommitted);
end;
destructor TEntityManagerFirebird.destroy;
begin
inherited;
FreeAndNil(fConnection);
end;
procedure TEntityManagerFirebird.close;
begin
fConnection.Close();
end;
procedure TEntityManagerFirebird.beginTransaction;
begin
fConnection.SetAutoCommit(False);
end;
procedure TEntityManagerFirebird.commitTransaction;
begin
fConnection.Commit;
fConnection.SetAutoCommit(True);
end;
procedure TEntityManagerFirebird.rollbackTransaction;
begin
fConnection.Rollback;
fConnection.SetAutoCommit(True);
end;
procedure TEntityManagerFirebird.persist(entity: TDpaEntity);
var
fPreparedStatement : IZPreparedStatement;
fResultSet : IZResultSet;
begin
fPreparedStatement := getSelectKeyFieldsPreparedStatement(entity);
fPreparedStatement.ExecutePrepared();
fResultSet := fPreparedStatement.ExecuteQueryPrepared();
if (not fResultSet.Next()) then begin
fPreparedStatement := getInsertPreparedStatement(entity);
end else begin
fPreparedStatement := getUpdatePreparedStatement(entity);
end;
fPreparedStatement.ExecutePrepared();
end;
procedure TEntityManagerFirebird.remove(entity: TDpaEntity);
var
fPreparedStatement : IZPreparedStatement;
fResultSet : IZResultSet;
begin
fPreparedStatement := getDeletePreparedStatement(entity);
fPreparedStatement.ExecutePrepared();
end;
function TEntityManagerFirebird.find(entity: TDpaEntity): TDpaEntity;
begin
end;
function TEntityManagerFirebird.getFields(dpaFieldArray: TDpaFieldArray): String;
var
i : Integer;
keyFields : String;
begin
keyFields := '';
for i := 0 to Length(dpaFieldArray) - 1 do begin
keyFields := keyFields + TDpaField(dpaFieldArray[i]).columnName + ', ';
end;
if (keyFields = '') then begin
keyFields := '*';
end else begin
keyFields := Copy(keyFields, 1, Length(keyFields) - 2);
end;
Result := keyFields;
end;
function TEntityManagerFirebird.getFieldsParams(dpaFieldArray: TDpaFieldArray): String;
var
i : Integer;
keyFields : String;
begin
keyFields := '';
for i := 0 to Length(dpaFieldArray) - 1 do begin
keyFields := keyFields + TDpaField(dpaFieldArray[i]).columnName + '=?, ';
end;
if (keyFields = '') then begin
keyFields := '*';
end else begin
keyFields := Copy(keyFields, 1, Length(keyFields) - 2);
end;
Result := keyFields;
end;
function TEntityManagerFirebird.getFieldsParamsAnd(dpaFieldArray: TDpaFieldArray): String;
var
i : Integer;
keyFields : String;
begin
keyFields := '';
for i := 0 to Length(dpaFieldArray) - 1 do begin
keyFields := keyFields + TDpaField(dpaFieldArray[i]).columnName + '=? and ';
end;
if (keyFields = '') then begin
keyFields := '*';
end else begin
keyFields := Copy(keyFields, 1, Length(keyFields) - 5);
end;
Result := keyFields;
end;
function TEntityManagerFirebird.getSelectPreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaFieldArray := entity.getFields();
fPreparedStatement := fConnection.PrepareStatement('select ' + getFields(fDpaFieldArray) + ' from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getSelectKeyFieldsPreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaKeyFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaKeyFieldArray := entity.getKeyFields();
fPreparedStatement := fConnection.PrepareStatement('select ' + getFields(fDpaKeyFieldArray) + ' from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaKeyFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaKeyFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getInsertPreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaFieldArray := entity.getFields();
fPreparedStatement := fConnection.PrepareStatement('insert into ' + entity.getTableName() + ' ' + '(' + getFields(fDpaFieldArray) + ')' + ' ' + 'values' + '(' + Copy(DupeString('?, ', Length(fDpaFieldArray)), 1, Length(DupeString('?, ', Length(fDpaFieldArray))) - 2) + ')');
setParamsPreparedStatement(fPreparedStatement, [fDpaFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getUpdatePreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaFieldArray : TDpaFieldArray;
fDpaKeyFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaFieldArray := entity.getFields();
fDpaKeyFieldArray := entity.getKeyFields();
fPreparedStatement := fConnection.PrepareStatement('update ' + entity.getTableName() + ' ' + 'set' + ' ' + getFieldsParams(fDpaFieldArray) + ' ' + 'where' + ' ' + getFieldsParamsAnd(fDpaKeyFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaFieldArray, fDpaKeyFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getDeletePreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaKeyFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaKeyFieldArray := entity.getKeyFields();
fPreparedStatement := fConnection.PrepareStatement('delete from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaKeyFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaKeyFieldArray]);
Result := fPreparedStatement;
end;
procedure TEntityManagerFirebird.setParamsPreparedStatement(var preparedStatement : IZPreparedStatement; dpaFieldArrays : array of TDpaFieldArray);
var
i, j : Integer;
paramCount : Integer;
begin
paramCount := 0;
for i := 0 to Length(dpaFieldArrays) - 1 do begin
for j := 0 to Length(dpaFieldArrays[i]) - 1 do begin
paramCount := paramCount + 1;
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldShortint)) then begin
preparedStatement.SetShort(paramCount, TDpaFieldShortint (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldSmallint)) then begin
preparedStatement.SetShort(paramCount, TDpaFieldSmallint (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldInteger )) then begin
preparedStatement.SetInt (paramCount, TDpaFieldInteger (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldLongint )) then begin
preparedStatement.SetLong (paramCount, TDpaFieldLongint (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldByte )) then begin
preparedStatement.SetByte (paramCount, TDpaFieldByte (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldWord )) then begin
preparedStatement.SetInt (paramCount, TDpaFieldWord (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldLongWord)) then begin
preparedStatement.SetLong (paramCount, TDpaFieldLongWord(TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldString )) then begin
preparedStatement.SetString(paramCount, TDpaFieldString (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldClob )) then begin
preparedStatement.SetString(paramCount, TDpaFieldClob (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end;
end;
end;
end;
end.
Posted: 20.05.2011, 15:00
by trupka
you can't (and don't need to) freeAndNil interfaced object because they are reference counted and automaticaly freed when not needed. IMO, it is sufficient to:
Code: Select all
destructor TEntityManagerFirebird.destroy;
begin
fConnection.CLose;
fConnection := nil;
inherited;
end;
I tried to generate memory leaks (see sample project in attach) without success. This could mean that the leak is actually in some other part of the code.
JavaPauloMG, can you test my sample?
Posted: 24.05.2011, 12:58
by JavaPauloMG
Hi my friend, i have test following the way you show me, and the memory leak only have ocorrured when i execute the statment, but when i execute de statment "remove" the error don't ocorrurs:
Code: Select all
procedure TEntityManagerFirebird.persist(entity: TDpaEntity);
var
fPreparedStatement : IZPreparedStatement;
fResultSet : IZResultSet;
begin
fPreparedStatement := getSelectKeyFieldsPreparedStatement(entity);
fPreparedStatement.ExecutePrepared();
fResultSet := fPreparedStatement.ExecuteQueryPrepared();
if (not fResultSet.Next()) then begin
fPreparedStatement := getInsertPreparedStatement(entity);
end else begin
fPreparedStatement := getUpdatePreparedStatement(entity);
end;
fPreparedStatement.ExecutePrepared();
end;
I now this is the sample code of memory leak:
Code: Select all
{*
@author João Paulo da Silva Simões
@version 0.1 - 2011/04/27
}
unit EntityManagerFirebird;
interface
uses
DpaEntity, EntityManager, DpaField, ZConnection, ZDbcIntfs, Dialogs;
type
TEntityManagerFirebird = class(TEntityManager)
private
{ Private declarations }
{*
}
fConnection : IZConnection;
{*
}
function getSelectPreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getSelectKeyFieldsPreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getInsertPreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getUpdatePreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getDeletePreparedStatement(entity : TDpaEntity) : IZPreparedStatement;
{*
}
function getFields(dpaFieldArray : TDpaFieldArray) : String;
{*
}
function getFieldsParams(dpaFieldArray : TDpaFieldArray) : String;
{*
}
function getFieldsParamsAnd(dpaFieldArray : TDpaFieldArray) : String;
{*
}
procedure setParamsPreparedStatement(var preparedStatement : IZPreparedStatement; dpaFieldArrays : array of TDpaFieldArray); overload;
protected
{ Protected declarations }
public
{ Public declarations }
{*
}
constructor create(protocol : String; hostname : String; database : String; user : String; password : String; dialect : String);
{*
}
destructor destroy(); override;
{*
}
procedure close(); override;
{*
}
procedure beginTransaction(); override;
{*
}
procedure commitTransaction(); override;
{*
}
procedure rollbackTransaction(); override;
{*
}
procedure persist(entity : TDpaEntity); override;
{*
}
procedure remove(entity : TDpaEntity); override;
{*
}
function find(entity : TDpaEntity) : TDpaEntity; override;
published
{ Published declarations }
end;
implementation
uses SysUtils, StrUtils;
{ TEntityManagerFirebird }
constructor TEntityManagerFirebird.create(protocol : String; hostname : String; database : String; user : String; password : String; dialect : String);
begin
fConnection := DriverManager.GetConnection('zdbc:' + protocol + ':' + '//' + hostname + '/' + database + '?username=' + user + ';password=' + password);
fConnection.SetAutoCommit(True);
fConnection.SetTransactionIsolation(tiReadCommitted);
end;
destructor TEntityManagerFirebird.destroy;
begin
fConnection.CLose;
fConnection := nil;
inherited;
end;
procedure TEntityManagerFirebird.close;
begin
fConnection.Close();
end;
procedure TEntityManagerFirebird.beginTransaction;
begin
fConnection.SetAutoCommit(False);
end;
procedure TEntityManagerFirebird.commitTransaction;
begin
fConnection.Commit;
fConnection.SetAutoCommit(True);
end;
procedure TEntityManagerFirebird.rollbackTransaction;
begin
fConnection.Rollback;
fConnection.SetAutoCommit(True);
end;
procedure TEntityManagerFirebird.persist(entity: TDpaEntity);
var
fPreparedStatement : IZPreparedStatement;
fResultSet : IZResultSet;
begin
fPreparedStatement := getSelectKeyFieldsPreparedStatement(entity);
fPreparedStatement.ExecutePrepared();
fResultSet := fPreparedStatement.ExecuteQueryPrepared();
if (not fResultSet.Next()) then begin
fPreparedStatement := getInsertPreparedStatement(entity);
end else begin
fPreparedStatement := getUpdatePreparedStatement(entity);
end;
fPreparedStatement.ExecutePrepared();
end;
procedure TEntityManagerFirebird.remove(entity: TDpaEntity);
var
fPreparedStatement : IZPreparedStatement;
fResultSet : IZResultSet;
begin
fPreparedStatement := getDeletePreparedStatement(entity);
fPreparedStatement.ExecutePrepared();
end;
function TEntityManagerFirebird.find(entity: TDpaEntity): TDpaEntity;
begin
end;
function TEntityManagerFirebird.getFields(dpaFieldArray: TDpaFieldArray): String;
var
i : Integer;
keyFields : String;
begin
keyFields := '';
for i := 0 to Length(dpaFieldArray) - 1 do begin
keyFields := keyFields + TDpaField(dpaFieldArray[i]).columnName + ', ';
end;
if (keyFields = '') then begin
keyFields := '*';
end else begin
keyFields := Copy(keyFields, 1, Length(keyFields) - 2);
end;
Result := keyFields;
end;
function TEntityManagerFirebird.getFieldsParams(dpaFieldArray: TDpaFieldArray): String;
var
i : Integer;
keyFields : String;
begin
keyFields := '';
for i := 0 to Length(dpaFieldArray) - 1 do begin
keyFields := keyFields + TDpaField(dpaFieldArray[i]).columnName + '=?, ';
end;
if (keyFields = '') then begin
keyFields := '*';
end else begin
keyFields := Copy(keyFields, 1, Length(keyFields) - 2);
end;
Result := keyFields;
end;
function TEntityManagerFirebird.getFieldsParamsAnd(dpaFieldArray: TDpaFieldArray): String;
var
i : Integer;
keyFields : String;
begin
keyFields := '';
for i := 0 to Length(dpaFieldArray) - 1 do begin
keyFields := keyFields + TDpaField(dpaFieldArray[i]).columnName + '=? and ';
end;
if (keyFields = '') then begin
keyFields := '*';
end else begin
keyFields := Copy(keyFields, 1, Length(keyFields) - 5);
end;
Result := keyFields;
end;
function TEntityManagerFirebird.getSelectPreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaFieldArray := entity.getFields();
fPreparedStatement := fConnection.PrepareStatement('select ' + getFields(fDpaFieldArray) + ' from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getSelectKeyFieldsPreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaKeyFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaKeyFieldArray := entity.getKeyFields();
fPreparedStatement := fConnection.PrepareStatement('select ' + getFields(fDpaKeyFieldArray) + ' from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaKeyFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaKeyFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getInsertPreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaFieldArray := entity.getFields();
fPreparedStatement := fConnection.PrepareStatement('insert into ' + entity.getTableName() + ' ' + '(' + getFields(fDpaFieldArray) + ')' + ' ' + 'values' + '(' + Copy(DupeString('?, ', Length(fDpaFieldArray)), 1, Length(DupeString('?, ', Length(fDpaFieldArray))) - 2) + ')');
setParamsPreparedStatement(fPreparedStatement, [fDpaFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getUpdatePreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaFieldArray : TDpaFieldArray;
fDpaKeyFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaFieldArray := entity.getFields();
fDpaKeyFieldArray := entity.getKeyFields();
fPreparedStatement := fConnection.PrepareStatement('update ' + entity.getTableName() + ' ' + 'set' + ' ' + getFieldsParams(fDpaFieldArray) + ' ' + 'where' + ' ' + getFieldsParamsAnd(fDpaKeyFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaFieldArray, fDpaKeyFieldArray]);
Result := fPreparedStatement;
end;
function TEntityManagerFirebird.getDeletePreparedStatement(entity: TDpaEntity): IZPreparedStatement;
var
fDpaKeyFieldArray : TDpaFieldArray;
fPreparedStatement : IZPreparedStatement;
begin
fDpaKeyFieldArray := entity.getKeyFields();
fPreparedStatement := fConnection.PrepareStatement('delete from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaKeyFieldArray));
setParamsPreparedStatement(fPreparedStatement, [fDpaKeyFieldArray]);
Result := fPreparedStatement;
end;
procedure TEntityManagerFirebird.setParamsPreparedStatement(var preparedStatement : IZPreparedStatement; dpaFieldArrays : array of TDpaFieldArray);
var
i, j : Integer;
paramCount : Integer;
begin
paramCount := 0;
for i := 0 to Length(dpaFieldArrays) - 1 do begin
for j := 0 to Length(dpaFieldArrays[i]) - 1 do begin
paramCount := paramCount + 1;
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldShortint)) then begin
preparedStatement.SetShort(paramCount, TDpaFieldShortint (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldSmallint)) then begin
preparedStatement.SetShort(paramCount, TDpaFieldSmallint (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldInteger )) then begin
preparedStatement.SetInt (paramCount, TDpaFieldInteger (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldLongint )) then begin
preparedStatement.SetLong (paramCount, TDpaFieldLongint (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldByte )) then begin
preparedStatement.SetByte (paramCount, TDpaFieldByte (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldWord )) then begin
preparedStatement.SetInt (paramCount, TDpaFieldWord (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldLongWord)) then begin
preparedStatement.SetLong (paramCount, TDpaFieldLongWord(TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldString )) then begin
preparedStatement.SetString(paramCount, TDpaFieldString (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end else
if (TDpaField(TDpaFieldArray(dpaFieldArrays[i])[j]).InheritsFrom(TDpaFieldClob )) then begin
preparedStatement.SetString(paramCount, TDpaFieldClob (TDpaFieldArray(dpaFieldArrays[i])[j]).value);
end;
end;
end;
end;
end.
Code: Select all
{*
@author João Paulo da Silva Simões
@version 0.1 - 2011/05/05
}
unit DpaField;
interface
type
TDpaField = class(TObject)
private
{ Private declarations }
fColumnName : String;
fKey : Boolean;
function getColumnName() : String;
function getKey() : Boolean;
procedure setColumnName(value : String);
procedure setKey(value : Boolean);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean);
destructor Destroy; override;
property columnName : String read getColumnName write setColumnName;
property key : Boolean read getKey write setKey;
published
{ Published declarations }
end;
type
TDpaFieldArray = array of TDpaField;
type
TDpaFieldShortint = class(TDpaField)
private
{ Private declarations }
fValue : Shortint;
function getValue() : Shortint;
procedure setValue(value : Shortint);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : Shortint read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldSmallint = class(TDpaField)
private
{ Private declarations }
fValue : Smallint;
function getValue() : Smallint;
procedure setValue(value : Smallint);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : Smallint read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldInteger = class(TDpaField)
private
{ Private declarations }
fValue : Integer;
function getValue() : Integer;
procedure setValue(value : Integer);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : Integer read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldLongint = class(TDpaField)
private
{ Private declarations }
fValue : Longint;
function getValue() : Longint;
procedure setValue(value : Longint);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : Longint read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldByte = class(TDpaField)
private
{ Private declarations }
fValue : Byte;
function getValue() : Byte;
procedure setValue(value : Byte);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : Byte read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldWord = class(TDpaField)
private
{ Private declarations }
fValue : Word;
function getValue() : Word;
procedure setValue(value : Word);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : Word read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldLongWord = class(TDpaField)
private
{ Private declarations }
fValue : LongWord;
function getValue() : LongWord;
procedure setValue(value : LongWord);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : LongWord read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldString = class(TDpaField)
private
{ Private declarations }
fValue : String;
function getValue() : String;
procedure setValue(value : String);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : String read getValue write setValue;
published
{ Published declarations }
end;
type
TDpaFieldClob = class(TDpaField)
private
{ Private declarations }
fValue : WideString;
function getValue() : WideString;
procedure setValue(value : WideString);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(columnName : String; key : Boolean); reintroduce;
destructor Destroy; override;
property value : WideString read getValue write setValue;
published
{ Published declarations }
end;
implementation
{ TDpaField }
constructor TDpaField.Create(columnName : String; key : Boolean);
begin
fColumnName := columnName;
fKey := key;
end;
destructor TDpaField.Destroy;
begin
inherited;
{}
end;
function TDpaField.getColumnName: String;
begin
Result := fColumnName;
end;
function TDpaField.getKey: Boolean;
begin
Result := fKey;
end;
procedure TDpaField.setColumnName(value: String);
begin
fColumnName := value;
end;
procedure TDpaField.setKey(value: Boolean);
begin
fKey := value;
end;
{ TDpaFieldInteger }
constructor TDpaFieldInteger.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldInteger.Destroy;
begin
inherited;
{}
end;
function TDpaFieldInteger.getValue: Integer;
begin
Result := fValue;
end;
procedure TDpaFieldInteger.setValue(value: Integer);
begin
fValue := value;
end;
{ TDpaFieldShortint }
constructor TDpaFieldShortint.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldShortint.Destroy;
begin
inherited;
{}
end;
function TDpaFieldShortint.getValue: Shortint;
begin
Result := fValue;
end;
procedure TDpaFieldShortint.setValue(value: Shortint);
begin
fValue := value;
end;
{ TDpaFieldSmallint }
constructor TDpaFieldSmallint.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldSmallint.Destroy;
begin
inherited;
{}
end;
function TDpaFieldSmallint.getValue: Smallint;
begin
Result := fValue;
end;
procedure TDpaFieldSmallint.setValue(value: Smallint);
begin
fValue := value;
end;
{ TDpaFieldLongint }
constructor TDpaFieldLongint.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldLongint.Destroy;
begin
inherited;
{}
end;
function TDpaFieldLongint.getValue: Longint;
begin
fValue := 0;
end;
procedure TDpaFieldLongint.setValue(value: Integer);
begin
fValue := value;
end;
{ TDpaFieldByte }
constructor TDpaFieldByte.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldByte.Destroy;
begin
inherited;
{}
end;
function TDpaFieldByte.getValue: Byte;
begin
Result := fValue;
end;
procedure TDpaFieldByte.setValue(value: Byte);
begin
fValue := value;
end;
{ TDpaFieldWord }
constructor TDpaFieldWord.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldWord.Destroy;
begin
inherited;
{}
end;
function TDpaFieldWord.getValue: Word;
begin
Result := fValue;
end;
procedure TDpaFieldWord.setValue(value: Word);
begin
fValue := value;
end;
{ TDpaFieldLongWord }
constructor TDpaFieldLongWord.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := 0;
end;
destructor TDpaFieldLongWord.Destroy;
begin
inherited;
{}
end;
function TDpaFieldLongWord.getValue: LongWord;
begin
Result := fValue;
end;
procedure TDpaFieldLongWord.setValue(value: LongWord);
begin
fValue := value;
end;
{ TDpaFieldString }
constructor TDpaFieldString.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := '';
end;
destructor TDpaFieldString.Destroy;
begin
inherited;
{}
end;
function TDpaFieldString.getValue: String;
begin
Result := fValue;
end;
procedure TDpaFieldString.setValue(value: String);
begin
fValue := value;
end;
{ TDpaFieldClob }
constructor TDpaFieldClob.Create(columnName : String; key : Boolean);
begin
inherited Create(columnName, key);
fValue := '';
end;
destructor TDpaFieldClob.Destroy;
begin
inherited;
{}
end;
function TDpaFieldClob.getValue: WideString;
begin
Result := fValue;
end;
procedure TDpaFieldClob.setValue(value: WideString);
begin
fValue := value;
end;
end.
Code: Select all
{*
@author João Paulo da Silva Simões
@version 0.1 - 2011/05/05
}
unit Tabela;
interface
uses
DpaEntity, DpaField,
SysUtils;
type
TTabela = class(TDpaEntity)
private
{ Private declarations }
{*
}
fId : TDpaFieldInteger;
fNome : TDpaFieldString ;
fTexto : TDpaFieldClob ;
{*
}
function getId: Integer;
function getNome: String;
function getTexto: WideString;
{*
}
procedure setId(value: Integer);
procedure setNome(value: String);
procedure setTexto(value: WideString);
protected
{ Protected declarations }
public
{ Public declarations }
{*
}
constructor Create;
{*
}
destructor Destroy; override;
{*
}
property id : Integer read getId write setId ;
property nome : String read getNome write setNome ;
property texto : WideString read getTexto write setTexto;
{*
}
function getTableName() : String; override;
{*
}
function getFields() : TDpaFieldArray; override;
published
{ Published declarations }
end;
implementation
uses TypInfo;
{ TTabela }
constructor TTabela.Create;
begin
inherited;
fId := TDpaFieldInteger.Create('id' , True );
fNome := TDpaFieldString .Create('nome' , False);
fTexto := TDpaFieldClob .Create('texto', False);
end;
destructor TTabela.Destroy;
begin
inherited;
FreeAndNil(fId );
FreeAndNil(fNome );
FreeAndNil(fTexto);
end;
function TTabela.getFields: TDpaFieldArray;
var
fDpaFieldArray : TDpaFieldArray;
begin
SetLength(fDpaFieldArray, 3);
fDpaFieldArray[0] := fId ;
fDpaFieldArray[1] := fNome ;
fDpaFieldArray[2] := fTexto;
Result := fDpaFieldArray;
end;
function TTabela.getId: Integer;
begin
Result := fId.value;
end;
function TTabela.getNome: String;
begin
Result := fNome.value;
end;
function TTabela.getTableName: String;
begin
Result := 'Tabela'
end;
function TTabela.getTexto: WideString;
begin
Result := fTexto.value;
end;
procedure TTabela.setId(value: Integer);
begin
fId.value := value;
end;
procedure TTabela.setNome(value: String);
begin
fNome.value := value;
end;
procedure TTabela.setTexto(value: WideString);
begin
fTexto.value := value;
end;
end.
This is the event when the memory leaks ocorrur:
Code: Select all
procedure TForm1.btnTmpClick(Sender: TObject);
var
entity : TTabela;
entityManagerFirebird : TEntityManagerFirebird;
begin
entity := TTabela.Create();
entityManagerFirebird := TEntityManagerFirebird.create('firebird-2.1', '127.0.0.1', 'C:\Desenvolvimento\OODelphiBasicImplementation\BANCO.FDB', 'SYSDBA', 'masterkey', '3');
entityManagerFirebird.persist(entity);
FreeAndNil(entity);
FreeAndNil(entityManagerFirebird);
end;
This is the script i have use to test this simple application:
Code: Select all
/* Table: TABELA, Owner: SYSDBA */
CREATE TABLE "TABELA"
(
"ID" INTEGER NOT NULL,
"NOME" VARCHAR(50),
"TEXTO" BLOB SUB_TYPE TEXT SEGMENT SIZE 1,
CONSTRAINT "PK_TABELA" PRIMARY KEY ("ID")
);
I use, Delphi 7 Professional, and ZeosLib 6.6.6.
Thanks if you can help-me, to catch the memory leaks i use the EurekaLog Trial.
Posted: 24.05.2011, 14:30
by JavaPauloMG
I make some more tests, and the memory leaks only ocorrurs when the prepared statement, execute a select statement, the erro not ocorrurs, when are a update, insert, or delete statment.
Posted: 25.05.2011, 12:28
by JavaPauloMG
I discover the error, when i use de IZPreparedStatement, with a "select" command, the memory leak, ocorrurs, but when i use IZStatment, so make a "select" the memory leak don't ocorrurs, somebody can tell me if this is a correct behavior? or i use the wrong component to make a simple "select?"
This is the code when the memomy leaks ocorrurs :
Code: Select all
fPreparedStatement := fConnection.PrepareStatement('select ' + getFields(fDpaKeyFieldArray) + ' from ' + entity.getTableName() + ' where ' + getFieldsParamsAnd(fDpaKeyFieldArray));
I want to use the IZPreparedStatment, do make a "select" command, because this interface accept add params...
Posted: 26.05.2011, 14:00
by JavaPauloMG
It's me again, i discover my error, this a sample how the error occurs:
Code: Select all
procedure TForm1.btnTmpClick(Sender: TObject);
var
fConnection : IZConnection;
fPreparedStatement : IZPreparedStatement;
begin
fConnection := DriverManager.GetConnection('zdbc:firebird-2.1://127.0.0.1/C:\Desenvolvimento\OODelphiBasicImplementation\BANCO.FDB?username=SYSDBA;password=masterkey;dialect=3');
fPreparedStatement := fConnection.PrepareStatement('select * from RDB$INDICES;');
fPreparedStatement.ExecutePrepared;
end;
Now this is the same code, with a simple modification ;
Code: Select all
procedure TForm1.btnTmpClick(Sender: TObject);
var
fConnection : IZConnection;
fPreparedStatement : IZPreparedStatement;
begin
fConnection := DriverManager.GetConnection('zdbc:firebird-2.1://127.0.0.1/C:\Desenvolvimento\OODelphiBasicImplementation\BANCO.FDB?username=SYSDBA;password=masterkey;dialect=3');
fPreparedStatement := fConnection.PrepareStatement('select * from RDB$INDICES;');
fPreparedStatement.ExecuteQueryPrepared;
end;
My conclusion, every time when we use the "IZPreparedStatment", to make a simple "select" command, we need to use this statement "ExecuteQueryPrepared", and the memory leaks don't occurs.
Thank to all have help-me in this singular question.
Posted: 26.05.2011, 19:36
by trupka
Hi,
I did some tests and came to similar conclusion - leak happens deeper in code, in Firebird dbc layer. Strictly speaking, it's not a bug in Zeos - low level programming needs more attention.
Posted: 18.09.2011, 21:41
by mdaems
Now a little question, why would you do a ExecutePrepared, which only returns a boolean (success or failure of a statement), when you're passing a select query? A select query implies a resultset is needed, which is only returned by ExecuteQueryPrepared.
Which explains why ExecutePrepared might cause a memory leak: probably the result of your query is loaded somehow but not released.
Not sure where it's cleaned up in ExecuteQueryPrepared. I guess (but it's just a guess!!) it's cleaned up automatically when Delphi notices you don't assign the result to a variable, freeing the resultset again.
Mark