sharemem.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. { *********************************************************************** }
  2. { }
  3. { Delphi / Kylix Cross-Platform Runtime Library }
  4. { }
  5. { Copyright (c) 1995-2005 Borland Software Corporation }
  6. { }
  7. { *********************************************************************** }
  8. unit ShareMem;
  9. interface
  10. {$IFDEF MEMORY_DIAG}
  11. type
  12. TBlockEnumProc = function (Block: Pointer): Boolean;
  13. {$ENDIF}
  14. function SysGetMem(Size: Integer): Pointer;
  15. function SysFreeMem(P: Pointer): Integer;
  16. function SysReallocMem(P: Pointer; Size: Integer): Pointer;
  17. function SysAllocMem(Size: Cardinal): Pointer;
  18. function SysRegisterExpectedMemoryLeak(P: Pointer): Boolean;
  19. function SysUnregisterExpectedMemoryLeak(P: Pointer): Boolean;
  20. function GetHeapStatus: THeapStatus;
  21. function GetAllocMemCount: Integer;
  22. function GetAllocMemSize: Integer;
  23. procedure DumpBlocks;
  24. procedure HeapAddRef;
  25. procedure HeapRelease;
  26. {$IFDEF MEMORY_DIAG}
  27. function InitBlockMarking: Boolean;
  28. function MarkBlocks: Integer;
  29. function GetMarkedBlocks(MarkID: Integer; Proc: TBlockEnumProc): Boolean;
  30. {$ENDIF}
  31. implementation
  32. {$IFDEF GLOBALALLOC}
  33. uses Windows;
  34. {$ENDIF}
  35. {$IFDEF MEMORY_DIAG}
  36. type
  37. TInitBlockMarking = function: Boolean;
  38. TMarkBlocks = function: Integer;
  39. TGetMarkedBlocks = function (MarkID: Integer; Proc: TBlockEnumProc): Boolean;
  40. var
  41. MMHandle: Integer = 0;
  42. SysInitBlockMarking: TInitBlockMarking = nil;
  43. SysMarkBlocks: TMarkBlocks = nil;
  44. SysGetMarkedBlocks: TGetMarkedBlocks = nil;
  45. {$ENDIF}
  46. var
  47. {Need access to the shared memory manager structure to be able to call the
  48. default AllocMem and leak registration handlers for borlndmm.dll libraries
  49. that do not implement these functions.}
  50. SharedMemoryManager: TMemoryManagerEx;
  51. const
  52. DelphiMM = 'borlndmm.dll';
  53. function SysGetMem(Size: Integer): Pointer; external DelphiMM name '@Borlndmm@SysGetMem$qqri';
  54. function SysFreeMem(P: Pointer): Integer; external DelphiMM name '@Borlndmm@SysFreeMem$qqrpv';
  55. function SysReallocMem(P: Pointer; Size: Integer): Pointer; external DelphiMM name '@Borlndmm@SysReallocMem$qqrpvi';
  56. function GetHeapStatus: THeapStatus; external DelphiMM;
  57. function GetAllocMemCount: Integer; external DelphiMM;
  58. function GetAllocMemSize: Integer; external DelphiMM;
  59. procedure DumpBlocks; external DelphiMM;
  60. function GetModuleHandle(lpModuleName: PChar): Integer; stdcall;
  61. external 'kernel32.dll' name 'GetModuleHandleA';
  62. function GetProcAddress(hModule: Integer; lpProcName: PChar): Pointer; stdcall;
  63. external 'kernel32.dll' name 'GetProcAddress';
  64. {$IFDEF MEMORY_DIAG}
  65. procedure InitMMHandle;
  66. begin
  67. if MMHandle = 0 then MMHandle := GetModuleHandle(DelphiMM);
  68. end;
  69. function InitBlockMarking: Boolean;
  70. begin
  71. InitMMHandle;
  72. if @SysInitBlockMarking = nil then
  73. @SysInitBlockMarking := GetProcAddress(MMHandle, 'InitBlockMarking');
  74. if @SysInitBlockMarking <> nil then
  75. Result := SysInitBlockMarking
  76. else Result := False;
  77. end;
  78. function MarkBlocks: Integer;
  79. begin
  80. InitMMHandle;
  81. if @SysMarkBlocks = nil then
  82. @SysMarkBlocks := GetProcAddress(MMHandle, 'MarkBlocks');
  83. if @SysMarkBlocks <> nil then
  84. Result := SysMarkBlocks
  85. else Result := -1;
  86. end;
  87. function GetMarkedBlocks(MarkID: Integer; Proc: TBlockEnumProc): Boolean;
  88. begin
  89. InitMMHandle;
  90. if @SysGetMarkedBlocks = nil then
  91. @SysGetMarkedBlocks := GetProcAddress(MMHandle, 'GetMarkedBlocks');
  92. if @SysGetMarkedBlocks <> nil then
  93. Result := SysGetMarkedBlocks(MarkID, Proc)
  94. else Result := False;
  95. end;
  96. {$ENDIF}
  97. {$IFDEF GLOBALALLOC}
  98. function xSysGetMem(Size: Integer): Pointer;
  99. begin
  100. Result := GlobalAllocPtr(HeapAllocFlags, Size);
  101. end;
  102. function xSysFreeMem(P: Pointer): Integer;
  103. begin
  104. Result := GlobalFreePtr(P);
  105. end;
  106. function xSysReallocMem(P: Pointer; Size: Integer): Pointer;
  107. begin
  108. Result := GlobalReallocPtr(P, Size, 0);
  109. end;
  110. {$ENDIF}
  111. procedure HeapAddRef;
  112. var
  113. MM: Integer;
  114. Proc: procedure;
  115. begin
  116. MM := GetModuleHandle(DelphiMM);
  117. Proc := GetProcAddress(MM, '@Borlndmm@HeapAddRef$qqrv');
  118. if Assigned(Proc) then
  119. Proc;
  120. end;
  121. procedure HeapRelease;
  122. var
  123. MM: Integer;
  124. Proc: procedure;
  125. begin
  126. MM := GetModuleHandle(DelphiMM);
  127. Proc := GetProcAddress(MM, '@Borlndmm@HeapRelease$qqrv');
  128. if Assigned(Proc) then
  129. Proc;
  130. end;
  131. {The default AllocMem implementation - for older borlndmm.dll libraries that do
  132. not implement this themselves.}
  133. function DefaultAllocMem(Size: Cardinal): Pointer;
  134. begin
  135. Result := SysGetMem(Size);
  136. if (Result <> nil) then
  137. FillChar(Result^, Size, 0);
  138. end;
  139. {The default (do nothing) leak registration function for backward compatibility
  140. with older borlndmm.dll libraries.}
  141. function DefaultRegisterAndUnregisterExpectedMemoryLeak(P: Pointer): boolean;
  142. begin
  143. Result := False;
  144. end;
  145. function SysAllocMem(Size: Cardinal): Pointer;
  146. begin
  147. {Indirect call, because the library may not implement this functionality}
  148. Result := SharedMemoryManager.AllocMem(Size);
  149. end;
  150. function SysRegisterExpectedMemoryLeak(P: Pointer): Boolean;
  151. begin
  152. {Indirect call, because the library may not implement this functionality}
  153. Result := SharedMemoryManager.RegisterExpectedMemoryLeak(P);
  154. end;
  155. function SysUnregisterExpectedMemoryLeak(P: Pointer): Boolean;
  156. begin
  157. {Indirect call, because the library may not implement this functionality}
  158. Result := SharedMemoryManager.UnregisterExpectedMemoryLeak(P);
  159. end;
  160. procedure InitMemoryManager;
  161. var
  162. ProcAddr: Pointer;
  163. MM: Integer;
  164. begin
  165. // force a static reference to borlndmm.dll, so we don't have to LoadLibrary
  166. SharedMemoryManager.GetMem := SysGetMem;
  167. MM := GetModuleHandle(DelphiMM);
  168. HeapAddRef;
  169. {$IFDEF GLOBALALLOC}
  170. SharedMemoryManager.GetMem := xSysGetMem;
  171. SharedMemoryManager.FreeMem := xSysFreeMem;
  172. SharedMemoryManager.ReallocMem := xSysReallocMem;
  173. {$ELSE}
  174. SharedMemoryManager.GetMem := GetProcAddress(MM,'@Borlndmm@SysGetMem$qqri');
  175. SharedMemoryManager.FreeMem := GetProcAddress(MM,'@Borlndmm@SysFreeMem$qqrpv');
  176. SharedMemoryManager.ReallocMem := GetProcAddress(MM, '@Borlndmm@SysReallocMem$qqrpvi');
  177. // Cannot assume that the functions below are implemented. Default handlers are set in initialization section.
  178. ProcAddr := GetProcAddress(MM,'@Borlndmm@SysAllocMem$qqri');
  179. if ProcAddr <> nil then
  180. SharedMemoryManager.AllocMem := ProcAddr;
  181. ProcAddr := GetProcAddress(MM,'@Borlndmm@SysRegisterExpectedMemoryLeak$qqrpi');
  182. if ProcAddr <> nil then
  183. SharedMemoryManager.RegisterExpectedMemoryLeak := ProcAddr;
  184. ProcAddr := GetProcAddress(MM, '@Borlndmm@SysUnregisterExpectedMemoryLeak$qqrpi');
  185. if ProcAddr <> nil then
  186. SharedMemoryManager.UnregisterExpectedMemoryLeak := ProcAddr;
  187. {$ENDIF}
  188. SetMemoryManager(SharedMemoryManager);
  189. end;
  190. initialization
  191. {Set the default handlers for older borlndmm.dll libraries that do not
  192. implement the extended memory manager functionality}
  193. SharedMemoryManager.AllocMem := DefaultAllocMem;
  194. SharedMemoryManager.RegisterExpectedMemoryLeak :=
  195. DefaultRegisterAndUnregisterExpectedMemoryLeak;
  196. SharedMemoryManager.UnregisterExpectedMemoryLeak :=
  197. DefaultRegisterAndUnregisterExpectedMemoryLeak;
  198. if not IsMemoryManagerSet then
  199. InitMemoryManager;
  200. finalization
  201. if IsMemoryManagerSet then
  202. HeapRelease;
  203. end.