BitLord
BitLord

Reputation: 187

Memory leak in Delphi XE3 when error happens on inserting into sqlite db

...
Query: TSQLQuery
...
    Query.SQL.Clear;
    Query.SQL.Add('INSERT INTO pumps'#13#10 +
                       'VALUES (NULL, :title, :power)');
    Query.ParamByName('title').AsString:= title;
    Query.ParamByName('power').AsFloat:= power;
    try
      Query.ExecSQL;
    except
      on E: Exception do
        begin
          ShowMessage(E.Message);
        end;
    end;

Query is linked to SQLConnection with driver=Sqlite. All the operations do work, but when I try to insert a non-unique value into the column with unique index, I get exception about value existance. OK, my code catches it and shows a message 'column title is not unique', but before debugger shows me that exception TWICE. When I close program, memory manager tells about memory leaks, and that leaks are:

Is it possible to avoid that?

UPD: I used FastMM4 to get detailed log, and below is a part about one memory leak:

A memory block has been leaked. The size is: 68

This block was allocated by thread 0xB18, and the stack trace (return addresses) at the time was:
4068A6 [System.pas][System][@GetMem$qqri][4203]
4082BB [System.pas][System][TObject.NewInstance$qqrv][14969]
4089D2 [System.pas][System][@ClassCreate$qqrpvzc][16231]
7D5A91 [Data.DbxSqlite.pas][Data.DbxSqlite][Dbxsqlite.TDBXSqliteCommand.$bctr$qqrp26Data.Dbxcommon.TDBXContextp35Data.Dbxsqlite.TDBXSqliteConnection][567]
6E3DFE [Data.DBXCommon][Generics.Collections.%TDictionary__2$20System.UnicodeStringp32Data.Dbxcommon.TDBXCreateCommand%.GetBucketIndex$qqrx20System.UnicodeStringi]
7D4C8E [Data.DbxSqlite.pas][Data.DbxSqlite][Dbxsqlite.TDBXSqliteDriver.CreateSqliteCommand$qqrp26Data.Dbxcommon.TDBXContextp29Data.Dbxcommon.TDBXConnectionp26Data.Dbxcommon.TDBXCommand][295]
6CE4DA [Data.DBXCommon.pas][Data.DBXCommon][Dbxcommon.TDBXDriver.CreateMorphCommand$qqrp26Data.Dbxcommon.TDBXContextp29Data.Dbxcommon.TDBXConnectionp26Data.Dbxcommon.TDBXCommand][7569]
6D5177 [Data.DBXCommon.pas][Data.DBXCommon][Dbxcommon.TDBXDelegateDriver.CreateMorphCommand$qqrp26Data.Dbxcommon.TDBXContextp29Data.Dbxcommon.TDBXConnectionp26Data.Dbxcommon.TDBXCommand][11061]
6D09F4 [Data.DBXCommon.pas][Data.DBXCommon][Dbxcommon.TDBXConnection.CreateMorphCommand$qqrp26Data.Dbxcommon.TDBXCommand][8480]
6D1C21 [Data.DBXCommon.pas][Data.DBXCommon][Dbxcommon.TDBXMorphicCommand.DerivedOpen$qqrv][9084]
6D1974 [Data.DBXCommon.pas][Data.DBXCommon][Dbxcommon.TDBXCommand.Open$qqrv][8962]

The block is currently used for an object of class: TDBXSqliteCommand

Upvotes: 6

Views: 1113

Answers (1)

Sir Rufo
Sir Rufo

Reputation: 19116

I run tests with dbXpress SQLite and MySQL driver (XE3) and your code just leaks with SQLite (also get the double exception in debug mode) but it doesn't with MySQL.

IMHO this is a bug that should be reported to QC.

Stack Trace at first exception occurrence in debugger

:769cc41f KERNELBASE.RaiseException + 0x58
Data.DBXCommon.TDBXContext.Error(???,'column title is not unique')
Data.DbxSqlite.CheckError(19,???,$2F12738)
Data.DbxSqlite.TDBXSqliteCommand.DerivedExecuteQuery
Data.DBXCommon.TDBXCommand.ExecuteQuery
Data.DBXCommon.TDBXMorphicCommand.ExecuteQuery
Data.SqlExpr.TCustomSQLDataSet.ExecuteStatement
Data.SqlExpr.TCustomSQLDataSet.ExecSQL(???)
Data.SqlExpr.TSQLQuery.ExecSQL(???)
Main_ViewU.TForm1.RunQuery($2E7B870,'Title',10)
Main_ViewU.TForm1.Button1Click($2E85AD0)

Stack Trace at second exception occurrence in debugger

:769cc41f KERNELBASE.RaiseException + 0x58    // <-- Exception interrupts Destroy
Data.DBXCommon.TDBXContext.Error(???,'column title is not unique')
Data.DbxSqlite.CheckError(19,???,$2F12738)
Data.DbxSqlite.TDBXSqliteCommand.DerivedClose
Data.DBXCommon.TDBXCommand.Close
Data.DBXCommon.TDBXMorphicCommand.DerivedClose
Data.DBXCommon.TDBXCommand.Close
Data.DBXCommon.TDBXCommand.Destroy            // <-- DESTROY
Data.DBXCommon.TDBXMorphicCommand.Destroy     // <-- DESTROY
System.TObject.Free
Data.SqlExpr.TCustomSQLDataSet.CloseStatement
Data.SqlExpr.TCustomSQLDataSet.InternalFreeCommand
Data.SqlExpr.TCustomSQLDataSet.FreeCommand
Data.SqlExpr.TCustomSQLDataSet.ExecSQL(???)
Data.SqlExpr.TSQLQuery.ExecSQL(???)
Main_ViewU.TForm1.RunQuery($2E7B870,'Title',10)
Main_ViewU.TForm1.Button1Click($2E85AD0)

And that causes the Memory Leak ...

Upvotes: 3

Related Questions