Re: [DUG] DLL memory leaks
I didn't know that was possible. I'll investigate. Thanks. -Original Message- From: delphi-boun...@delphi.org.nz [mailto:delphi-boun...@delphi.org.nz] On Behalf Of Paul Heinz Sent: Sunday, 7 August 2011 4:24 p.m. To: NZ Borland Developers Group - Delphi List Subject: Re: [DUG] DLL memory leaks Ross asked: My app loads 3rd party DLL's. There is a freeware 3rd party DLL I distribute which has a memory leak in a rare situation. The DLL source is not available. Unloading the DLL doesn't free the RAM. I guess Windows doesn't keep track of RAM allocations within DLL's. Is there any ability to determine the RAM allocated by the DLL and force this to be released when the DLL is unloaded? I'm guessing not but thought I would ask. I think you're right. I'm not aware that the Win32 heap and/or memory management tracks the module doing the allocating. Memory management is a whole address space kind of thing and DLL's live in your address space, essentially by definition. However, you could track that information yourself by patching the DLL's import table to redirect all it's memory allocation activity through your own shim routines which track the allocations and frees and forwards them through to the usual imported routine. Then you would have the information to be able to release the leaked memory on unload. You'd need to examine the DLL's import table with an appropriate tool to see which APIs it uses to allocate memory, eithe a run-time library DLL or direct API calls like VirtualAlloc/HeapAlloc, etc. to determine whether this is feasible. Cheers, Paul. ___ NZ Borland Developers Group - Delphi mailing list Post: delphi@delphi.org.nz Admin: http://delphi.org.nz/mailman/listinfo/delphi Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: unsubscribe ___ NZ Borland Developers Group - Delphi mailing list Post: delphi@delphi.org.nz Admin: http://delphi.org.nz/mailman/listinfo/delphi Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: unsubscribe
Re: [DUG] DLL memory leaks
Ross wrote: I didn't know that was possible. I'll investigate. PE Explorer is probably one of the best tools for this. It's also written in Delphi I believe. You can download a fully functional 30-day trial version. http://www.heaventools.com/download-pe-explorer.htm Alternatively, if you want to point me at the DLL, I can have a look at it's import table for you. Import Address Table (or IAT) patching is a pretty standard albeit 'low-level' technique. If you look for sample code around the web, it's often more involved that it needs to be since it's often written in the context of injecting DLLs into other processes you don't control to patch their main import table. Since you'll be patching the import table of a DLL you've loaded into your own process, it's much simpler. Here's the routine I use. It's using HInstance rather than the module handle for a loaded DLL since I used for patching the main executable's import table. You'll want to pass the module handle of your DLL by calling GetModuleHandle. It returns the current IAT entry so you can easily forward chain. There's a whole bunch of stanard PE table record type definitions this code depends on which I've left out. function InstallWin32Hook(const ModuleName, FuncName: string; HookFunc: Pointer): Pointer; var NTHeader: PImageNTHeaders; ImportDesc: PImageImportDescriptor; Thunk: PImageThunkData; begin Result := GetProcAddress(GetModuleHandle(PChar(ModuleName)), PChar(FuncName)); if Result nil then begin NTHeader := PImageNTHeaders(DWord(HInstance) + PImageDosHeader(HInstance).e_lfanew); ImportDesc := PImageImportDescriptor(DWord(HInstance) + NTHeader.OptionalHeader.DataDirectory[ImageDirectoryEntryImport].Virtual Address); while ImportDesc.Name 0 do begin if StriComp(PAnsiChar(DWord(HInstance) + ImportDesc.Name), PAnsiChar(AnsiString(ModuleName))) = 0 then begin Thunk := PImageThunkData(DWord(HInstance) + DWord(ImportDesc.FirstThunk)); while Thunk.Funct nil do begin if Thunk.Funct = Result then Thunk.Funct := HookFunc; Inc(Thunk) end end; Inc(ImportDesc) end end end; And here's how its used with a sample shim: var OldRaiseException: procedure (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWord; const lpArguments: DWord); stdcall; OldRaiseException := InstallWin32Hook(Kernel32, 'RaiseException', @HookRaiseException); procedure HookRaiseException(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWord; const lpArguments: DWord); stdcall; begin { If this is a real Delphi exception and has the arguments as we expect from System._RaiseExcept then we can crack the argument structure and determine if we need to take a stack trace. Note that this may change from version to version of Delphi. } if (dwExceptionCode = cDelphiException) and (lpArguments 0) and (nNumberOfArguments = 7) and not InHookRaise then with PDelphiExceptionArguments(lpArguments)^ do try InHookRaise := True; if not IgnoreException(ExceptObject) then HookStackTrace(ExceptAddress, EBP, ESP, False); finally InHookRaise := False; end; if Assigned(OldRaiseException) then OldRaiseException(dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments); end; Cheers, Paul. ___ NZ Borland Developers Group - Delphi mailing list Post: delphi@delphi.org.nz Admin: http://delphi.org.nz/mailman/listinfo/delphi Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: unsubscribe
Re: [DUG] DLL memory leaks
Ross asked: My app loads 3rd party DLL's. There is a freeware 3rd party DLL I distribute which has a memory leak in a rare situation. The DLL source is not available. Unloading the DLL doesn't free the RAM. I guess Windows doesn't keep track of RAM allocations within DLL's. Is there any ability to determine the RAM allocated by the DLL and force this to be released when the DLL is unloaded? I'm guessing not but thought I would ask. I think you're right. I'm not aware that the Win32 heap and/or memory management tracks the module doing the allocating. Memory management is a whole address space kind of thing and DLL's live in your address space, essentially by definition. However, you could track that information yourself by patching the DLL's import table to redirect all it's memory allocation activity through your own shim routines which track the allocations and frees and forwards them through to the usual imported routine. Then you would have the information to be able to release the leaked memory on unload. You'd need to examine the DLL's import table with an appropriate tool to see which APIs it uses to allocate memory, eithe a run-time library DLL or direct API calls like VirtualAlloc/HeapAlloc, etc. to determine whether this is feasible. Cheers, Paul. ___ NZ Borland Developers Group - Delphi mailing list Post: delphi@delphi.org.nz Admin: http://delphi.org.nz/mailman/listinfo/delphi Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: unsubscribe