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
- Build with debug info in the executable:
dcc64 -$O- -$W+ -V -U"<BDS>\lib\win64\debug;..."
- Run under a leak detector (I used Deleaker) and take a snapshot right after startup.
- Open a SQLite file, then click a table so the editor loads it.
- 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
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.
RestoreListSetupcreates fiveTStringList(one directly, four viaExplode) but reassignsValueListeach time, so theFreeon line 377 releases only the last. Up to four leak per call, and the procedure is called from 15 places.TAppSettings.Create: localrx: TRegExprnever freed. The destructor does the same thing correctly on 4202/4219.Tconnform.FormShow:LastSessionsnever freed.RefreshSessions:SessionNamesnever freed. Recursive, so once per folder.TfrmTableEditor.Init: localrx: TRegExprnever freed.GetKeyImageIndexes, which returns a newTList<Integer>, never freed.TSQLFunctionList.Create:TryFilesandSectionsnever freed.Needs an ownership decision, so listed separately:
TConnectionParametersis passed toAddChildas node data. There is noOnFreeNodehandler, soListSessions.Clearon line 351 drops the pointers. One per session, on every refresh.TTableColumn, 77TTableKey, 41TStringMap, 26TDBObject.FSQLFunctionsassigned inDoAfterConnect, never freed. Owns its items, so 76TSQLFunctiongo with it. Per connection.PostponedLogItemsnever 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
dcc64 -$O- -$W+ -V -U"<BDS>\lib\win64\debug;..."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
RestoreListSetupcreates fiveTStringListinstances and frees one.Error/Backtrace