Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

sqlite

delphi

...
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:

  • 21 - 28 bytes: UnicodeString x 4
  • 61 - 68 bytes: TDBXSqliteCommand x2
  • 69 - 76 bytes: TDBXMorphicCommand x 2
  • 221 - 236 bytes: Unknown x 2

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
like image 1000
BitLord Avatar asked Jan 10 '13 18:01

BitLord


People also ask

What is memory leak in Delphi?

Every time when we no longer use an object in our code, we should delete it, by freeing the memory it was allocated. If we don't do this, our program can allocate more and more memory as it runs. This will also fail to remove unwanted blocks of memory is called a memory leak.

What is a database memory leak?

In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory which is no longer needed is not released.


1 Answers

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 ...

like image 120
Sir Rufo Avatar answered Sep 24 '22 15:09

Sir Rufo