国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Delphi > 正文

Delphi中的包(一):關(guān)于exe的編譯、連接和執(zhí)行

2019-11-18 17:57:23
字體:
供稿:網(wǎng)友

最近搞Delphi,發(fā)現(xiàn)原來的程序中使用了很多包,但是總是處于懵懵懂懂的狀態(tài)。索性來好好研究一下這個(gè)問題,可能要花一些時(shí)間。所以首先把需要分析的問題列出來:
什么是包?什么是exe?它們在組成上有什么不同?包跟dcu是什么關(guān)系?dcp是干什么的?這些文件在編譯時(shí)是什么關(guān)系?又是怎么裝載的?裝載了以后怎么樣操作包?dll可以exports,但是為什么delphi幫助中不提包的exports,但是有些代碼卻又在包中使用exPRots?

首先來看看delphi的編譯過程。delphi的工程中有兩類:包和程序,前者的后綴為dpk,后者為dpr。從簡單的開始,先來搞dpr。根據(jù)delphi的幫助文檔,一個(gè)典型的dpr文件的結(jié)構(gòu)如下:
 1 program Editor;
 2    
 3     uses
 4       Forms, {change to QForms in linux}
 5       REAbout in 'REAbout.pas' {AboutBox},
 6       REMain in 'REMain.pas' {MainForm};
 7    
 8     {$R *.res}
 9    
10     begin
11       application.Title := 'Text Editor';
12       Application.CreateForm(TMainForm, MainForm);
13       Application.Run;
14     end.
其中10行到14行,begin…end很自然就是程序的執(zhí)行入口。uses部分指明了程序需要使用的一些Unit,這個(gè)就比較含糊了,為什么有的會用in指明源代碼的位置(這部分是自己向工程中添加的),有的如Forms這個(gè)部分,卻又不需要?那每個(gè)Unit又會uses其它Unit,這個(gè)問題似乎越來越復(fù)雜了。先看整個(gè)源代碼的結(jié)構(gòu):

我猜測編譯器第一步首先遍歷這張有向圖,對每個(gè)Unit,如果有必要就對其進(jìn)行編譯,生成對應(yīng)的dcu。而這個(gè)“必要”問題,我開始以為是use這個(gè)Unit的語句是帶有in的,后來試驗(yàn)發(fā)現(xiàn)不對。因?yàn)樵谏厦娴那闆r下,Unit3并沒有在Unit1的Uses子句中指明路徑,但是仍然正確產(chǎn)生了對應(yīng)的dcu文件。后來使用filemon來監(jiān)視文件打開情況,發(fā)現(xiàn)過程是這樣的:對于圖中的每個(gè)節(jié)點(diǎn),編譯器按照當(dāng)前目錄—project屬性中的search path—IDE環(huán)境中的library path,這樣的順序,搜索節(jié)點(diǎn)對應(yīng)的pas文件,沒找到就再來一遍,但是這次搜索的是節(jié)點(diǎn)對應(yīng)的dcu文件。

現(xiàn)在編譯搞定了,每個(gè)Unit(即pas文件)已經(jīng)生成了對于的dcu文件,下面的問題是連接。說到連接,問題就復(fù)雜了,連接有兩種:靜態(tài)和動態(tài)。靜態(tài)連接就是說把這些dcu全部合并到一起。這樣,一個(gè)Unit對另一個(gè)Unit的調(diào)用,就成了程序內(nèi)部的事情了。這樣的好處是快,而且簡單,并發(fā)共享之類的問題都容易處理。缺點(diǎn)是目標(biāo)程序很大,而且如果現(xiàn)在要編寫另一個(gè)程序,而Unit3可以重用的話,則在連接時(shí)Unit3.dcu被再次拷貝。這樣在兩個(gè)程序同時(shí)運(yùn)行時(shí),內(nèi)存中會有兩個(gè)Unit3的副本,比較浪費(fèi)。動態(tài)連接就是說,兩個(gè)程序在連接時(shí),僅僅只保留對Unit3的引用,而并不拷貝Unit3的內(nèi)容。到運(yùn)行時(shí),把Unit3裝入內(nèi)存,讓兩個(gè)程序公用。Dll和BPL都是動態(tài)連接的解決方案。問題在于,delphi中關(guān)于連接的選項(xiàng)就只有project|Options|packages菜單中出現(xiàn),“Build with runtime packages”這句話實(shí)在是太模糊了。所以還要再研究一下。
在程序執(zhí)行的時(shí)候,我們可以通過view|debug window|moudles來查看有哪些東西被加載到內(nèi)存中去了,它們又包含哪些內(nèi)容。
簡便起見,我們建立如下結(jié)構(gòu)的一個(gè)程序:


program ProjectEXE;


uses
  Forms,
  Windows,
  UnitFormMain in 'UnitFormMain.pas' {FormMain};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TFormMain, FormMain);
  Application.Run;
end.


unit UnitFormMain;

interface

uses
  Windows, StdCtrls, Forms, UnitFormAnother,Classes, Controls;

type
  TFormMain = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;

implementation

{$R *.dfm}

procedure TFormMain.Button1Click(Sender: TObject);
var
  LForm:TFormAnother;
begin
  LForm:=TFormAnother.Create(Application);
  LForm.ShowModal;
  LForm.Free;
end;

end.


unit UnitFormAnother;

interface

uses
  Forms;

type
  TFormAnother = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

end.


“Build with runtime packages”不打鉤的時(shí)候,是靜態(tài)連接的。有向圖中出現(xiàn)的所有Unit都包含在目標(biāo)文件中了,整個(gè)exe有356k,而兩個(gè)Unit各自只有4k。
現(xiàn)在來動態(tài)?!癇uild with runtime packages”打鉤,現(xiàn)在發(fā)現(xiàn)運(yùn)行時(shí)ProjectEXE.exe文件只包含四個(gè)部分:兩個(gè)Form、一個(gè)SysInit.pas、一個(gè)ProjectEXE.dpr;與此同時(shí)進(jìn)程樹里面多了兩個(gè)bpl:rtl60和vcl60,它們的內(nèi)容就是剛才靜態(tài)連接中出現(xiàn)的那些Unit。現(xiàn)在ProjectEXE.exe只有16k。也就是說,有向圖中的Unit,一部分放在exe中了,另一部分放在bpl中了。但是根據(jù)什么來劃分呢?是根據(jù)uses子句,還是根據(jù)這里“Build with runtime packages”中的列表?繼續(xù)測試,發(fā)現(xiàn):如果列表中僅包含vcl60,則加載到內(nèi)存中的還是兩個(gè)bpl加一個(gè)exe;如果列表中只包含rtl60,則內(nèi)存中僅包含rtl60和exe,但是exe的內(nèi)容發(fā)生了變化:里面的Unit增多了,而且基本都是vcl60包里面的。我猜想應(yīng)該是rtl和vcl包之間存在require關(guān)系。這個(gè)留到下一步再測試。但是初步估計(jì)連接過程中,肯定會利用包列表,將那些已經(jīng)在包中存在的Unit從exe中排除出去。

在動態(tài)連接之后,還存在一個(gè)問題:裝入。裝入有兩種策略,靜態(tài)也稱為自動,由delphi生成代碼,在裝載exe之前,自動裝入包;另一種是動態(tài),即在程序運(yùn)行時(shí)通過編碼,指定一個(gè)包,把它裝入內(nèi)存。問題在于,我必須搞清楚delphi在什么情況下會自動裝入一個(gè)包,什么情況下可以避免delphi自作聰明,這樣才能靈活地使用包。前面的試驗(yàn)中,只可以看出,在dpr文件執(zhí)行到begin之前,靜態(tài)連接的的包就已經(jīng)裝入內(nèi)存了。具體過程我也不清楚,等下一章開始寫自己的包,再來做實(shí)驗(yàn)吧。



上一篇:Delphi中的包(三):bpl和dll

下一篇:李維看Delphi2006(DeXter)

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 武邑县| 且末县| 钟山县| 绩溪县| 宁阳县| 台江县| 莱西市| 九龙县| 英超| 镇赉县| 政和县| 高青县| 宿迁市| 屏南县| 邻水| 讷河市| 新乡县| 吴江市| 满洲里市| 都兰县| 洛宁县| 元朗区| 宜黄县| 汾西县| 灵璧县| 江北区| 剑阁县| 类乌齐县| 慈利县| 杭锦旗| 广西| 晋宁县| 吴旗县| 惠东县| 山丹县| 元阳县| 桃园市| 兴城市| 新民市| 宜春市| 莱州市|