TServiceManager.QueryServiceConfig() creates a memory leak
Summary
TServiceManager.QueryServiceConfig() creates a memory leak.
System Information
- Operating system: Windows 11
- Processor architecture: x86-64, AARCH64 (FPC runs as true x64 version on native Windows 11 on ARM64.)
- Compiler version: 3.2.2, trunk
Steps to reproduce
Call TServiceManager.QueryServiceConfig()
with Heaptrc enabled. In my case 388 bytes got allocated via GetMem()
but only 328 bytes released via FreeMem()
.
Example Project
Attached a simple sample project for Windows with Heaptrc on: ServiceManagerMemoryLeak.zip
What is the current bug behavior?
Memory allocated gets not fully released as the actual size gets overridden as BytesNeeded
is used twice in the actual Windows API call QueryServiceConfig(SHandle,SvcCfg,
BytesNeeded
,BytesNeeded)
.
What is the expected (correct) behavior?
Full release of memory allocated.
Possible fixes
Here is a simple fix for trunk: ServiceManager.diff
procedure TServiceManager.QueryServiceConfig(SHandle : THandle; Var Config : TServiceDescriptor);
Var
SvcCfg : PQueryServiceConfig;
BytesNeeded, BytesSize : DWord;
begin
{$IFDEF FPC_DOTTEDUNITS}WinApi.Jedi.WinSvc{$ELSE}jwawinsvc{$ENDIF}.QueryServiceConfig(SHandle,Nil,0,BytesNeeded);
If (GetLastError<>ERROR_INSUFFICIENT_BUFFER) then
RaiseLastOSError;
BytesSize := BytesNeeded;
GetMem(SvcCfg,BytesSize);
Try
If Not {$IFDEF FPC_DOTTEDUNITS}WinApi.Jedi.WinSvc{$ELSE}jwawinsvc{$ENDIF}.QueryServiceConfig(SHandle,SvcCfg,BytesSize,BytesNeeded) then
RaiseLastOSError;
With config,SvcCfg^ do
begin
Password:='';
Name:='';
DesiredAccess:=0;
ErrorControl:=dwErrorControl;
ServiceType:=dwServiceType;
StartType:=dwStartType;
TagID:=dwTagID;
CommandLine:=lpBinaryPathName;
LoadOrderGroup:=lpLoadOrderGroup;
Dependencies:=lpDependencies;
UserName:=lpServiceStartName;
DisplayName:=lpDisplayName;
end;
Finally
FreeMem(SvcCfg,BytesSize);
end;
end;