#1 2012-09-20 09:44:24

Leander007
Member
From: Slovenia
Registered: 2011-04-29
Posts: 113

Memory leak using interface implementation ISQLDBRows and SQLite3

Hi, I noticed that interface implementation of next code produces memory leaks:

var
  locDB: TSQLDBConnectionProperties;
  sql: RawUtf8;
  rows: ISQLDBRows;
begin
  locDB := TSQLDBSQLite3ConnectionProperties.Create(StringToUTF8('someDB.db'),'','','');
  try
    sql := 'select someColumn from someTable where...';
    rows := locDB.Execute(sql,[]);//* produces memory leak    
    while rows.Step do //* and each step produces memory leak too
    begin
	  (...)
    end;   
  finally
    locDB.Free;
  end;
end;

and this does not:

var
  locDB: TSQLDBConnectionProperties;
  sql: RawUtf8;
  rows: TSQLDBStatement;
begin
  locDB := TSQLDBSQLite3ConnectionProperties.Create(StringToUTF8('someDB.db'),'','','');
  try
    sql := 'select someColumn from someTable where...';
    rows := locDB.NewThreadSafeStatement;
    try
      rows.Execute(SQL,true);
      while rows.Step do
      begin
	(...)
      end;
    finally
      rows.Free;
    end;
  finally
    locDB.Free;
  end;
end;

"Uncertainty in science: There no doubt exist natural laws, but once this fine reason of ours was corrupted, it corrupted everything.", Blaise Pascal

Offline

#2 2012-09-20 11:40:48

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,201
Website

Re: Memory leak using interface implementation ISQLDBRows and SQLite3

The TSQLDBConnectionProperties instance should not be released before the ISQLDBRows instance, which is the case in your code.

This is a well known limitation (feature?) of any Delphi interface: the rows.Free is created by the compiler at the end of this method with an hidden try..finally block - see our articles about this.

You should not use a ISQLDBRows interface in such cases, but a regular TSQLDBStatement instance.
In fact, this code is correct:

var
  locDB: TSQLDBConnectionProperties;
  sql: RawUtf8;
  rows: TSQLDBStatement;
begin
  locDB := TSQLDBSQLite3ConnectionProperties.Create(StringToUTF8('someDB.db'),'','','');
  try
    sql := 'select someColumn from someTable where...';
    rows := locDB.Execute(sql,[]);//* produces memory leak   
    try
      while rows.Step do //* and each step produces memory leak too
      begin
  	  (...)
      end;    
    finally
      rows.Free;
    end;
  finally
    locDB.Free;
  end;
end;

In the framework, TSQLDBConnectionProperties  instances are mostly system-wide so you won't suffer for this.

Offline

#3 2012-09-20 12:08:40

Leander007
Member
From: Slovenia
Registered: 2011-04-29
Posts: 113

Re: Memory leak using interface implementation ISQLDBRows and SQLite3

Sorry for bothering you, that was my mistake smile.
I know when the interface goes out of scope.
I didn't really look the source code about relationship between locDB and rows (in this case).
So I didn't realized importance of "destruction" sequence.


"Uncertainty in science: There no doubt exist natural laws, but once this fine reason of ours was corrupted, it corrupted everything.", Blaise Pascal

Offline

Board footer

Powered by FluxBB