dll和exe内存共享问题。
有这样一个现象:
当exe和dll引用同一个forms.pas文件以后,那么请看下面代码:
library mydll
interface
uses
windows,sysutils,forms;
procedure test;external;stdcall;
implementation
{$R *.res}
procedure test;external;stdcall;
begin
showmessage(application.title);
end;
end.
///////////////////////////////////
program myexe
uses
windows,sysutils,forms;
{$R *.res}
var
hlib:dword;
p:tprocedure;
begin
application.initialize;
application.title:='ok!'
hlib:=loadlibrary("mydll.dll");
p:=getprocaddress(hlib,"test");
if assigned(p) then p();//竟然能够显示'ok!'
freelibrary(hlib);
application.run;
end.
//////////////////////////
我们知道,application是forms.pas单元中的全局变量。
dll里面并没有对application做初始化,但是调用test的时候,dll里访问了在exe中做好了初始化的application变量。
问题:
是不是因为同一个进程中exe和dll共享一切内存,完全透明,并且只要引用了同一个单元,那么在任何编译好的pe文件中,该单元的资源,比如全局变量、常量、函数等,都被固化到了相同的rva地址?
问题点数:50、回复次数:15Top
1 楼stanely(俺是邢她汉子)回复于 2004-04-01 10:42:54 得分 0
?Top
2 楼nyf1220(我是党员----不过听说最近风声紧,打算换名字)回复于 2004-04-01 11:10:22 得分 5
d5开发指南中讲过
dll中的application对象与调用它的程序是分离的,
应该是没有什么关系
但是为什么显示ok,不知道了~
等高人吧~Top
3 楼alphax(豪言壮语的乌鸦)回复于 2004-04-01 11:39:58 得分 45
不是这样的,dll的那个application的title就是exe的application.title
如果你这样调用
application.initialize;
application.title := 'abc';
hlib:=loadlibrary("mydll.dll"); //now the library cache the application module
//name to it's title property, the value is
//abc
application.title :='ok!' //now we change to 'ok', but the dll application
//property Title will not changed
p:=getprocaddress(hlib,"test");
if assigned(p) then
begin
p(); //here, it will be show 'abc' rather 'ok'
end;
freelibrary(hlib);
application.run;Top
4 楼highbury(海布里)回复于 2004-04-01 11:41:04 得分 0
动态库里加入uses ShareMem有用吗Top
5 楼stanely(俺是邢她汉子)回复于 2004-04-02 00:19:45 得分 0
"//now the library cache the application "?
怎么个cache法?
如何解答:
“是不是因为同一个进程中exe和dll共享一切内存,完全透明,并且只要引用了同一个单元,那么在任何编译好的pe文件中,该单元的资源,比如全局变量、常量、函数等,都被固化到了相同的rva地址?”
Top
6 楼halfdream(哈欠)回复于 2004-04-02 09:29:46 得分 0
关注。。
Top
7 楼alphax(豪言壮语的乌鸦)回复于 2004-04-02 10:18:29 得分 0
因为你的DLL间接引用了Controls,而Controls会导致Application的初始化
你可以参考TApplication.Create()的代码,它里面有对Title属性的初始化
对于一个DLL或Package,它的Title被初始化为宿主应用程序(exe)的Module Name,
也就是title,但是一旦这个DLL的Application对象的Title被初始化后,不管exe方面怎样变化它就不再变化了,所以我说它把module name cache起来了,关于这一点,
详见TApplication.GetTitle()的代码
以上就是你给出的例子以及我改后的例子之所以得出那样的结果的原因
至于你说的
是不是因为同一个进程中exe和dll共享一切内存,完全透明,
并且只要引用了同一个单元,那么在任何编译好的pe文件中,该单元的资源,
比如全局变量、常量、函数等,都被固化到了相同的rva地址?”
则是错误的,dll中的所有单元和exe中的所有单元都是分离的,各自都有一个副本
的Top
8 楼alphax(豪言壮语的乌鸦)回复于 2004-04-02 10:22:08 得分 0
再补充一下
dll中的所有单元和exe中的所有单元都是分离的,各自都有一个副本
的,除非它们都build with runtime library,那么这些被build with
的runtime library中的单元的数据则是共享的Top
9 楼jie115(守望红木)回复于 2004-04-02 11:02:29 得分 0
markTop
10 楼jie115(守望红木)回复于 2004-04-02 11:26:31 得分 0
我看了这些代码,但是能解释一下,哪里可以看出来title 被 module name cache啊。
-------------------
function TApplication.GetTitle: string;
var
Buffer: array[0..255] of Char;
begin
if FHandleCreated then
SetString(Result, Buffer, GetWindowText(FHandle, Buffer,
SizeOf(Buffer))) else
Result := FTitle;
end;
procedure TApplication.SetTitle(const Value: string);
begin
if FHandleCreated then
begin
if (GetTitle <> Value) or (FTitle <> '') then
begin
SetWindowText(FHandle, PChar(Value));
FTitle := '';
end;
end
else
FTitle := Value;
end;
这里只是设定ftitle,设置ftitle而已啊,当然同时设定了windowtest。
Top
11 楼jie115(守望红木)回复于 2004-04-02 12:03:34 得分 0
windowtest-》windowtextTop
12 楼alphax(豪言壮语的乌鸦)回复于 2004-04-02 12:13:32 得分 0
你再看看TApplication.Create()Top
13 楼stanely(俺是邢她汉子)回复于 2004-04-02 22:55:57 得分 0
你这 jie115(守望红木) ,真会借花献佛阿!Top
14 楼halfdream(哈欠)回复于 2004-04-03 10:22:21 得分 0
呵。这问题这样就结贴了?
Top
15 楼horse_h(小马)回复于 2004-04-17 17:32:14 得分 0
gzTop




