(okwary) 小叹的学习园地

与天斗?不够高~ 与地斗?不够阔 与人斗? 脸皮不够厚

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 

 

(okwary) 小叹的学习园地

DLLs中的全局内存 

Windows规定:

DLLs并不拥有它打开的任何文件或它分配的任何全局内存块。这些对象由直接或间接调用DLLs的应用程序拥有。这样,当应用程序中止时,它拥有的打开的文件自动关闭,它拥有的全局内存块自动释放。这就意味着保存在DLLs全局变量中的文件和全局内存块变量在DLLs没有被通知的情况下就变为非法。这将给其它使用该DLLs的应用程序造成困难。

为了避免出现这种情况,文件和全局内存块句柄不应作为DLLs的全局变量,而是作为DLLs中过程或函数的参数传递给DLLs使用。调用DLLs的应用程序应该负责对它们的维护。

但在特定情况下,DLLs也可以拥有自己的全局内存块。这些内存块必须用gmem_DDEShare属性进行分配。这样的内存块直到被DLLs显示释放或DLLs退出时都保持有效。

由DLLs管理的全局内存块是应用程序间进行数据传输的又一途径,下面我们将专门讨论这一问题。 

 

利用DLLs实现应用程序间的数据传输的步骤为:

1. 编写一个DLLs程序,其中拥有一个用gmem_DDEShare属性分配的全局内存块;

2. 服务器程序调用DLLs,向全局内存块写入数据;

3. 客户程序调用DLLs,从全局内存块读取数据。 


用于实现数据传输的DLLs的编写 

用于实现数据传输的DLLs与一般DLLs的编写基本相同,其中特别的地方是:

1. 定义一个全局变量句柄: 

var

hMem: THandle;

2. 定义一个过程,返回该全局变量的句柄。该过程要包含在exports子句中。如: 

function GetGlobalMem: THandle; export;

begin

Result := hMem;

end;

3. 在初始化代码中分配全局内存块:

程序清单如下: 

begin

hMem := GlobalAlloc(gmem_MOVEABLE and gmem_DDEShare,num);

if hMem = 0 then

MessageDlg('Could not allocate memory',mtWarning,[mbOK],0);

end.

//num是一个预定义的常数。

Windows API函数GlobalAlloc用于从全局内存堆中分配一块内存,并返回该内存块的句柄。该函数包括两个参数,第一个参数用于设置内存块的分配标志。可以使用的分配标志如下表所示。

表10.3 全局内存块的分配标志

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
标 志 意 义
—————————————————————————————————

gmem_DDEShare 分配可由应用程序共享的内存

gmem_Discardable 分配可抛弃的内存(只与gmem_Moveable连用)

gmem_Fixed 分配固定内存

gmem_Moveable 分配可移动的内存

gmem_Nocompact 该全局堆中的内存不能被压缩或抛弃

gmem_Nodiscard 该全局堆中的内存不能被抛弃

gmem_NOT_Banked 分配不能被分段的内存

gmem_Notify 通知功能。当该内存被抛弃时调用GlobalNotify函数

gmem_Zeroinit 将所分配内存块的内容初始化为零

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

 

GlobalAlloc

该函数从堆中分配一定数目的字节数.Win32内存管理器并不提供相互分开的局部和全局堆.提供这个函数只是为了与16位的Windows相兼容.

函数原型:

HGLOBAL GlobalAlloc(

UINT uFlags, // 分配属性(方式)

DWORD dwBytes // 分配的字节数

);


参数:

uFlags:      指定如何分配内存,若指定为0,则是默认的GMEM_FIXED.这个值可以是下面其中一个或几个位标识(那些指明不兼容的组合除外)

dwBytes :指定要申请的字节数.若该参数为 0 且参数 uFlags 指定为 GMEM_MOVEABLE 则该函数返回一个内存对象的句柄,该内存对象被标识为discarded(可抛弃的)


返回值:

若函数调用成功,则返回一个新分配的内存对象的句柄.

若函数调用失败,则返回 NULL.可调用 GetLastError 以获得更多错误信息.

注解:

如果堆内没有足够的空间满足请求,函数将返回 NULL.因为NULL是用于标明错误的,所以不会分配虚拟0地址.

因此很容易检测出是否在使用一个NULL指针.

使用此函数分配内存可以保证8字节的边界.所有的内存均在执行访问时创建;不需要特别的函数来动态执行所产生的代码.

若函数调用成功,将至少分配所需内存.若实际分配量超过所需,则内存仍然能够充分利用之.可用函数 GlobalSize 来确定实际所分配的字节数.

可使用 GlobalFree 来释放内存.


标识的含意:

GMEM_FIXED:分配固定的内存,返回值是一个指针.
GMEM_MOVEABLE:分配可移动的内存,在Win32中内存块在物理内存中是不可移动的,但在缺省堆中可以. 返回值是该内存对象的句柄,可使用函数 GlobalLock 将该句柄转换为一个指针.这个标识不能与 GMEM_FIXED 组合使用.
GPTR 标识 为GMEM_FIXED和GMEM_ZEROINIT组合.
GHND 标识 为GMEM_MOVEABLE 和 GMEM_ZEROINIT的组合.
GMEM_DDESHARE
GMEM_SHARE:这个标识是为与16位Windows兼容而提供的,一些应用程序可使用该标识加强DDE操作的功能因此当内存用于DDE时可使用此标识.
//[DDE说明:DDE 是Dynamic Data Exchange 即动态数据交换。是 16 位 Windows 时代实现不同应用程序之间互相交换数据和控制的技术 ]

GMEM_DISCARDABLE 标识:被忽略.这个标识只是为与 16 位 Windows 相兼容而提供的.在 Win32 中你必须显式地调用函数 GlobalDiscard 以抛弃一块内存.这个标识可与 GMEM_FIXED 组合使用.
GMEM_LOWER,GMEM_NOCOMPACT,GMEM_NODISCARD,GMEM_NOT_BANKED,GMEM_NOTIFY :均被忽略. 这个标识只是为与 16 位 Windows 相兼容而提供的.
GMEM_ZEROINIT :将所申请内存初始化为0.


 

 

posted on 2008-12-27 19:48  okwary  阅读(270)  评论(0编辑  收藏  举报
ggg