Skip to content

Several objects never freed (memory leaks) in forms, table editor and dbconnection #2574

Description

@ArtemRazin

Description

Profiling a 12.21 debug build shows a number of objects that are allocated and
never freed. Grouped by how safe they are to fix. Line numbers are against
effb854 (v12.21).

Straightforward: a local is created and never released.

Location Leak
extra_controls.pas:321, 328, 342, 354 RestoreListSetup creates five TStringList (one directly, four via Explode) but reassigns ValueList each time, so the Free on line 377 releases only the last. Up to four leak per call, and the procedure is called from 15 places.
apphelpers.pas:3810 TAppSettings.Create: local rx: TRegExpr never freed. The destructor does the same thing correctly on 4202/4219.
connections.pas:422 Tconnform.FormShow: LastSessions never freed.
connections.pas:355 RefreshSessions: SessionNames never freed. Recursive, so once per folder.
table_editor.pas:398 TfrmTableEditor.Init: local rx: TRegExpr never freed.
table_editor.pas:1358, 1386 Results of GetKeyImageIndexes, which returns a new TList<Integer>, never freed.
dbconnection.pas:11494, 11501 TSQLFunctionList.Create: TryFiles and Sections never freed.

Needs an ownership decision, so listed separately:

Location Leak
connections.pas:357 TConnectionParameters is passed to AddChild as node data. There is no OnFreeNode handler, so ListSessions.Clear on line 351 drops the pointers. One per session, on every refresh.
table_editor.pas:287-292 Six containers created in the constructor, and the unit has no destructor. They own their contents, so a single table opened leaks 190 TTableColumn, 77 TTableKey, 41 TStringMap, 26 TDBObject.
dbconnection.pas:3493 FSQLFunctions assigned in DoAfterConnect, never freed. Owns its items, so 76 TSQLFunction go with it. Per connection.
heidisql.dpr:76 PostponedLogItems never freed. Possibly intentional.

Happy to send a PR for the first group.

HeidiSQL version and OS

12.21, Windows 11, built with Delphi 12.2

Database server version

SQLite (most of the leaks are independent of the server)

Reproduction recipe

  1. Build with debug info in the executable: dcc64 -$O- -$W+ -V -U"<BDS>\lib\win64\debug;..."
  2. Run under a leak detector (I used Deleaker) and take a snapshot right after startup.
  3. Open a SQLite file, then click a table so the editor loads it.
  4. Exit, and compare the post mortem state against the startup snapshot.

That run leaves 1153 unfreed Delphi objects, about 190 KB, with startup globals
already subtracted out by the comparison.

Most rows in the table above can also be confirmed by reading the code alone, for
example RestoreListSetup creates five TStringList instances and frees one.

Error/Backtrace

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmedIssue verified by project memberenhancementEnhances an existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions