转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
The Delphi Object Model (PART III)         ★★★★

The Delphi Object Model (PART III)

作者:闵涛 文章来源:闵涛的学习笔记 点击数:2532 更新时间:2009/4/23 18:43:52
ueToFlagErrors; fNext := NodeList; NodeList := Self; end; // If you want to clean up the list properly when the application // finishes, call RealFree for each node in the list. The inherited // FreeInstance method frees and cleans up the node for real. procedure TNode.RealFree; begin inherited FreeInstance; end;

You can also replace the entire memory management system that Delphi uses. Install a new memory manager by calling SetMemoryManager. For example, you might want to replace Delphi''''s suballocator with an allocator that performs additional error checking. Example 2-18 shows a custom memory manager that keeps a list of pointers the program has allocated and explicitly checks each attempt to free a pointer against the list. Any attempt to free an invalid pointer is refused, and Delphi will report a runtime error (which SysUtils changes to an exception). As a bonus, the memory manager checks that the list is empty when the application ends. If the list is not empty, you have a memory leak.

Example 2-18: Installing a Custom Memory Manager

unit CheckMemMgr;
 
interface
 
uses Windows;
 
function CheckGet(Size: Integer): Pointer;
function CheckFree(Mem: Pointer): Integer;
function CheckRealloc(Mem: Pointer; Size: Integer): Pointer;
 
var
  HeapFlags: DWord; // In a single-threaded application, you might
                    // want to set this to Heap_No_Serialize.
implementation
 
const
  MaxSize = MaxInt div 4;
type
  TPointerArray = array[1..MaxSize] of Pointer;
  PPointerArray = ^TPointerArray;
var
  Heap: THandle;             // Windows heap for the pointer list
  List: PPointerArray;       // List of allocated pointers
  ListSize: Integer;         // Number of pointers in the list
  ListAlloc: Integer;        // Capacity of the pointer list
 
// If the list of allocated pointers is not empty when the program
// finishes, that means you have a memory leak. Handling the memory
// leak is left as an exercise for the reader.
procedure MemoryLeak;
begin
  // Report the leak to the user, but remember that the program is
  // shutting down, so you should probably stick to the Windows API
  // and not use the VCL.
end;
 
// Add a pointer to the list.
procedure AddMem(Mem: Pointer);
begin
  if List = nil then
  begin
    // New list of pointers.
    ListAlloc := 8;
    List := HeapAlloc(Heap, HeapFlags, ListAlloc * SizeOf(Pointer));
  end
  else if ListSize >= ListAlloc then
  begin
    // Make the list bigger. Try to do it somewhat intelligently.
    if ListAlloc < 256 then
      ListAlloc := ListAlloc * 2
    else
      ListAlloc := ListAlloc + 256;
    List := HeapRealloc(Heap, HeapFlags, List,
                        ListAlloc * SizeOf(Pointer));
  end;
  // Add a pointer to the list.
  Inc(ListSize);
  List[ListSize] := Mem;
end;
 
// Look for a pointer in the list, and remove it. Return True for
// success, and False if the pointer is not in the list.
function RemoveMem(Mem: Pointer): Boolean;
var
  I: Integer;
begin
  for I := 1 to ListSize do
    if List[I] = Mem then
    begin
      MoveMemory(@List[I], @List[I+1], (ListSize-I) * SizeOf(Pointer));
      Dec(ListSize);
      Result := True;
      Exit;
    end;
 
  Result := False;
end;
 
// Replacement memory allocator.
function CheckGet(Size: Integer): Pointer;
begin
  Result := SysGetMem(Size);
  AddMem(Result);
end;
 
// If the pointer isn''''t in the list, don''''t call the real
// Free function. Return 0 for success, and non-zero for an error.
function CheckFree(Mem: Pointer): Integer;
begin
  if not RemoveMem(Mem) then
    Result := 1
  else
    Result := SysFreeMem(Mem);
end;
 
// Remove the old pointer and add the new one, which might be the
// same as the old one, or it might be different. Return nil for
// an error, and Delphi will raise an exception.
function CheckRealloc(Mem: Pointer; Size: Integer): Pointer;
begin
  if not RemoveMem(Mem) then
    Result := nil
  else
  begin
    Result :=SysReallocMem(Mem, Size);
    AddMem(Result);
  end;
end;
 
procedure SetNewManager;
var
  Mgr: TMemoryManager;
begin
  Mgr.GetMem := CheckGet;
  Mgr.FreeMem := CheckFree;
  Mgr.ReallocMem := CheckRealloc;
  SetMemoryManager(Mgr);
end;
 
initialization
  Heap := HeapCreate(0, HeapFlags, 0);
  SetNewManager;
finalization
  if ListSize <> 0 then
    MemoryLeak;
  HeapDestroy(Heap);
end.

If you define a custom memory manager, you must ensure that your memory manager is used for all memory allocation. The easiest way to do this is to set the memory manager in a unit''''s initialization section, as shown in Example 2-18. The memory management unit must be the first unit listed in the project''''s uses declaration.

Ordinarily, if a unit makes global changes in its initialization section, it should clean up those changes in its finalization section. A unit in a package might be loaded and unloaded many times in a single application, so cleaning up is important. A memory manager is different, though. Memory allocated by one manager cannot be freed by another manager, so you must ensure that only one manager is active in an application, and that the manager is active for the entire duration of the application. This means you must not put your memory manager in a package, although you can use a DLL, as explained in the next section.

Memory and DLLs

If you use DLLs and try to pass objects between DLLs or between the application and a DLL, you run into a number of problems. First of all, each DLL and EXE keeps its own copy of its class tables. The is and as operators do not work correctly for objects passed between DLLs and EXEs. Use packages (described in Chapter 1) to solve this problem. Another problem is that any memory allocated in a DLL is owned by that DLL. When Windows unloads the DLL, all memory allocated by the DLL is freed, even if the EXE or another DLL holds a pointer to that memory. This can be a major problem when using strings, dynamic arrays, and Variants because you never know when Delphi will allocate memory automatically.

The solution is to use the ShareMem unit as the first unit of your project and every DLL. The ShareMem unit installs a custom memory manager that redirects all memory allocation requests to a special DLL, BorlndMM.dll. The application doesn''''t unload BorlndMM until the application exits. The DLL magic takes place transparently, so you don''''t need to worry about the details. Just make sure you use the ShareMem unit, and make sure it is the first unit used by your program and libraries. When you release your application to your clients or customers, you will need to include BorlndMM.dll.

If you define your own memory manager, and you need to use DLLs, you must duplicate the magic performed by the ShareMem unit. You can replace ShareMem with your own unit that forwards memory requests to your DLL, which uses your custom memory manager. Example 2-19 shows one way to define your own replacement for the ShareMem unit.

Example 2-19: Defining a Shared Memory Manager

unit CheckShareMem;
 
// Use this unit first so all memory allocations use the shared
// memory manager. The application and all DLLs must use this unit.
// You cannot use packages because those DLLs use the default Borland
// shared memory manager.
 
interface
 
function CheckGet(Size: Integer): Pointer;
function CheckFree(Mem: Pointer): Integer;
function CheckRealloc(Mem: Pointer; Size: Integer): Pointer;
 
implementation
 
const
  DLL = ''''CheckMM.dll'''';
 
function CheckGet(Size: Integer): Pointer; external DLL;
function CheckFree(Mem: Pointer): Integer; external DLL;
function CheckRealloc(Mem: Pointer; Size: Integer): Pointer;
    external DLL;
 
procedure SetNewManager;
var
  Mgr: TMemoryManager;
begin
  Mgr.GetMem := CheckGet;
  Mgr.FreeMem := CheckFree;
  Mgr.ReallocMem := CheckRealloc;
  SetMemoryManager(Mgr);
end;
 
initialization
  SetNewManager;
end.

The CheckMM DLL uses your custom memory manager and exports its functions so they can be used by the CheckShareMem unit. Example 2-20 shows the source code for the CheckMM library.

Example 2-20: Defining the Shared Memory Manager DLL

library CheckMM;
 
// Replacement for BorlndMM.dll to use a custom memory manager.
 
uses
  CheckMemMgr;
 
exports
  CheckGet, CheckFree, CheckRealloc;
 
begin
end.

Your program and library projects use the CheckShareMem unit first, and all memory requests go to CheckMM.dll, which uses the error-checking memory manager. You don''''t often need to replace Delphi''''s memory manager, but as you can see, it isn''''t difficult to do.

TIP:
The memory manager that comes with Delphi works well for most applications, but it does not perform well in some cases. The average application allocates and frees memory in chunks of varying sizes. If your application is different and allocates memory in ever-increasing sizes (say, because you have a dynamic array that grows in small steps to a very large size), performance will suffer. Delphi''''s memory manager will allocate more memory than your application needs. One solution is to redesign your program so it uses memory in a different pattern (say, by preallocating a large dynamic array). Another solution is to write a memory manager that better meets the specialized needs of your application. For example, the new memory manager might use the Windows API (HeapAllocate, etc.).

Old-Style Object Types

In addition to class types, Delphi supports an obsolete type that uses the object keyword. Old-style objects exist for backward compatibi

上一页  [1] [2] [3]  下一页


[系统软件]InstallShield Express for delphi制作安装程序定…  [系统软件]The GRETA Regular Expression Template Archive
[系统软件]OLE with the internet explorer  [系统软件]14.5.10.1 Object creation expressions
[常用软件]InstallShield Express制作Delphi数据库安装程序  [常用软件]Firefox: What’s the next step?
[VB.NET程序]VB.Net中文教程(8)  对象(Object)基本概念  [VB.NET程序]The UDPChat Source(VB.NET)
[Delphi程序]为什么选择Delphi.Net ?  [Delphi程序]《关于VisiBroker For Delphi的使用》(4)
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台