怎样从Delphi中释放由Com中分配的内存。。(100分)

  • 主题发起人 主题发起人 zmxjh
  • 开始时间 开始时间
Z

zmxjh

Unregistered / Unconfirmed
GUEST, unregistred user!
我用VC写了一个组件,片段如下。

math::GetName(BSTR **bstrName)
{
*bstrName=SysAllocString(L"Zmxjh");
return S_OK;
}

math::GetTitle(char **pchar)
{
*pchar=CoTaskMemAlloc(10);
memcpy(.............);
return S_OK
}

现在Delphi中调用这两个方法,由于内存是由服务组件分析的,在Delphi中怎样释放
 
现在Delphi中调用这两个方法,由于内存是由服务组件分配的,在Delphi中怎样释放
 
由谁分配,就由谁释放,在组件中做
这和用什么调用无关
用Com只看到接口,不可能管到你内部分配什么
 
组件中分配内存的目的是将字符串返回给调用者,如果让组件分配了又释放,那怎样将字符串
返回给调用者呢!

COM的调用规则好像是由组件分配内存,客户释放内存吧!!据我所知。:)
 
Windows下编程向来是“谁使用,谁释放”的原则,你在组件里分配了内存,就理应在组件
里释放,或者提供释放内存的方法。这不是VC的问题也不是Delphi的问题,而是一个组件编
程的原则问题。
 
com好像有自动释放机制。
 
谢谢!WolfXP,stlont都很正确。

如果我现在的应用一定要在com中分配,由客户释放该怎么做。

或者我上面那个例子应该怎么改。

 
1. 客户分配内存
2. 调用组件,传递所分配内存指针作参数
3. 组件内部分配内存,处理数据
4. 组件将结果存入参数指向的内存
5. 组件释放内存

一定要在com中分配,由客户释放: 不行!别乱来!
还是那句话: 客户只看到接口,不可能管到你内部
建议你重温:对象的封装部分知识
 
像这种com分配内存,客户释放内存的例子,随便都可以抓一把来。
我上面那个例子是来自<ATL开发指南》第二版。

由于那上面的例子客户端是由VC写的。并且内存克实是由com分配客户释放的。
再次谢谢stlont。如果让你来写这个例子,你会怎么写呢?
COM:
我用VC写了一个组件,片段如下。

math::GetName(BSTR **bstrName)
{
*bstrName=SysAllocString(L"Zmxjh");
return S_OK;
}

math::GetTitle(char **pchar)
{
*pchar=CoTaskMemAlloc(10);
memcpy(.............);
return S_OK
}

delphi:
var
i:IMath;
str:WideString;
begin
........
i.GetName(str);
end;
程序结束后,由GetName分配的内存应该怎样释放,会自动释放吗?
 
stlont,我的QQ是:19033925,咱们交个朋友吧!
 
delphi:
var
i:IMath;
str:WideString; //[blue]1. 客户分配内存指针[/blue]
begin
........
i.GetName(str); //[blue]2. 调用组件,传递所分配内存指针作参数[/blue]

end;

*bstrName=SysAllocString(L"Zmxjh"); //[red]3. 组件内部分配内存,处理数据[/red]

4. 组件将结果存入参数指向的内存指针
5. 释放内存:
这里是组件把申请的内存给了参数的指针,内存现在是客户的了
所以你说的也有道理,但是这样应该在in-process的com才能用,其他的跨区com就
不能用了。
在我看来,这样做是不应该的,会造成混乱,书也不能照搬,最关键是
要懂原理,书有问题的地方要批判。
 
现在你也看到了,内存是客户的了,接下来,客户该怎么释放吗?

对于:SysAllocString
可用:SysFreeString(好像是这样拼的吧,不记得了:)

对于 CoTaskMemAlloc(10)
可用:CoTaskMemFree(..)(好像是这样拼的吧,不记得了:)

关键在于,这两个Free内存的API,怎样作用于以上Delphi客户中的str(str:WideString)呢!
在delphi直接使用CoTaskMemFree(str),好像会报错。具体应该怎么解决。:)
 
可以用SysFreeString释放SysAllocString
用法:
procedure SysFreeString(const S: WideString); stdcall;
external oleaut name 'SysFreeString';

不过在本例中,应该不用手工释放,form close时局部变量会处理的。
不相信你可以用内存工具查下有没有泄露。

再说一次:调用接口的人不一定知道你内部用的SysAllocString
所以客户端处理是不好的,不要这样编程。


 
stlont:
其本上我还是按你说的做的。在Com端添加了一个RemoveAll方法来做到的。

‘不相信你可以用内存工具查下有没有泄露’
谁能推荐一个这方面比较优秀的工具吗?我认为win2000中的任务管理就不错了。:)
 
对于这个server端分配的内存,我又仔细考虑了一下
结论是必须在客户端手工释放,否则会造成内存泄露
以前搞过的,也查过不少参考资料。

对于上一贴的结论如果误导了你,在此表示抱歉。
如果你的com给别人用,一定要说明用了SysAllocString
让client端用SysFreeString释放。

 
不管怎样,这次讨论对我的帮忙很大,我想抱歉也用不着了,必竟你的热心,是值得称道的。
我的解决方法如上所诉,在com添加了一个方法,由客户在调用了相关方法之后使用。
 
后退
顶部