日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[转] 《完美程式设计指南》Effective Delphi

發(fā)布時間:2025/5/22 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转] 《完美程式设计指南》Effective Delphi 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Effective Delphi

條款1:不管怎么樣,請讓你的Project至少user一次SysUtils.pas單元

很多使用Delphi的人都對Delphi有著這樣一個抱怨:Delphi雖然開發(fā)效率高,但是其編譯出來的程序卻是太大。使用Delphi5新建一個Project然后直接編譯,程序的Size就已經(jīng)達到了286KB,而如果把同樣的程序放到Delphi7下面編譯的話,那么其Size更是達到了360KB。正是由于這點,所以為Delphi編譯生成的應(yīng)用程序“減肥”便成為了幾乎所有Delphi社區(qū)的一個保留性話題。

其間,大多數(shù)人都是使用可執(zhí)行文件壓縮工具(比如Aspack或者Upx等)來壓縮Delphi所生成的可執(zhí)行文件以達到“減肥”的目的,但是也有一些人,他們使用一種更為極端,但是更有效的方式來減少Delphi編譯生成的可執(zhí)行文件的Size,那就是拋棄VCL所提供的編程框架,而直接使用WIN32 SDK加上Object Pascal所提供的面向?qū)ο髞砟軄磉M行程序的撰寫。比如以下一段程序,使用Delphi5的編譯器進行編譯其大小只有16KB,而寫一個基本的帶窗口的Window程序其大小也不會超過25KB(以下這段程序使用Delphi3編譯后會更小,其原因請見下述):

CODE: program SmallPro;

uses

Windows;

{$R *.RES}

begin

MessageBox(0, 'Hello World!', 'Information', MB_OK);

end. [Copy to clipboard]

請大家注意,以上程序是在project文件內(nèi)直接編譯,所以沒有引用到其它的自定義單元。而所包含的Windows單元則只是為了調(diào)用MessageBox API函數(shù)而必須包含的。

這個編譯出來的程序?qū)嵲谑翘×?#xff0c;小到它足以對那些熟悉Windows SDK方式編程,而又使用Delphi作為開發(fā)工具的人產(chǎn)生一定的誘惑力(我自己就算一個:->)。不知道這種方式是否同樣也對你產(chǎn)生過誘惑力或者已經(jīng)對你產(chǎn)生了誘惑力,如果是的話,那么先請聽我一句忠告,“請為你的Project Uese上SysUtils.pas單元吧,否則你的程序?qū)⑹ナ褂卯惓C制的能力,如果你不接這條忠告的話,你早晚會為你的行為任出代價。”

關(guān)于異常處理,各人的看法不同,有的人認為它是一種極美妙的錯誤處理方式:因為它能夠使程序代碼中處理錯誤部分的代碼與實現(xiàn)邏輯部分的代碼分離,使程序的源代碼變得更優(yōu)雅且撰寫起來更方便和易讀。而有人則認為使用異常機制來處理程序中的錯誤是不好的行為:因為一旦異常被觸發(fā),并且你未對其加控制的話,那么這個異常將導(dǎo)致應(yīng)用程序終止,這種錯誤處理方式太過直接和粗魯。但是,不管怎樣,無庸置疑一點的是,你的程序代碼可以不使用異常機制來處理錯誤,但是你卻無法預(yù)計在你的代碼當中所調(diào)用的各種庫函數(shù)或者類是否使用或者支持異常機制,所以為了保證你程序的魯棒性,即使你的代碼不使用異常機制,那么你也應(yīng)該在你代碼的關(guān)鍵位置,加入異常處理的代碼,以免你的代碼所調(diào)用的其它代碼或者操作系統(tǒng)拋出異常,導(dǎo)致程序意外的終止。下面便是一個簡單的小例了:

CODE: program SmallPro;

uses

Windows,

SysUtils;

{$R *.RES}

var

p: PChar;

begin

try

p := nil;

p^ := 'l';

except

MessageBox(0, 'Exception', 'Information', MB_OK);

end;

end. [Copy to clipboard]

以上程序向地址空間0x00000000寫一個字節(jié)的數(shù)據(jù),在現(xiàn)在所有版本的Windows操作系統(tǒng)下面,這都將被系統(tǒng)視為非法操作,所以操作系統(tǒng)會拋出一個SHE異常,而Delphi的RTL系統(tǒng)會使你的程序能夠欄截住這個異常并加以處理,如果你的程序沒有處理這個異常的話,那么Delphi的RTL會彈出一個顯示異常信息的對話框,并在你按下對話框的“確定”按鈕后終止整個程序。我們上面的程序處理了這個異常,程序?qū)⒃趶棾鯩essageBox函數(shù)所顯示的對話框后繼續(xù)執(zhí)行try…except.塊后面的代碼。

下面我們將上面的這個例子做一個很小的改動,將uses的SysUtils.pas單元去掉,然后再運行看看會出現(xiàn)什么樣結(jié)果。

程序執(zhí)行的結(jié)果和uses了SysUtils.pas單元的版本有著相當大的差異,程序只會顯示一個如下圖所示的:Runtime Error的對話框,然后便終止運行了,我們的異常處理塊try..except則根本就沒有起到作用。

(圖1:運行時錯誤)

 

經(jīng)過以上的測試,我想你已經(jīng)能夠明白,如果想讓你的使用Delphi編譯器所編譯出來的程序能夠支持異常機制的話,那么你就必須去在你的項目當中至少的包含的一次SysUtils.pas單元。寫到此處,此條款應(yīng)該可以說是功德圓滿,但是我想我還是有必要帶你簡單的了解一下Delphi的整個異常處理機制,以便你能夠?qū)ysUtils.pas單元在整個Delphi異常機制中所占的地位有一個進一步的認識,并能夠做到更好的使用它。

追根溯源,Delphi的編譯器其實會向C/C++編譯器一樣為你的程序在鏈接時插入一段啟動代碼來使操作系統(tǒng)能夠調(diào)用它,并啟動整個應(yīng)用程序(這個不是C/C++的main函數(shù),如果你對這方面感興趣的話,我建議你去讀Jeffry Richter所著的《Programming Applications for Microsoft Windows Fourth Edition》,這本書的第4章對Processes的講述中有相關(guān)的描述)。

對于以EXE形式存在的和以DLL形式存在的程序來說,Delphi為它們插入的啟動代碼的名稱是不一樣的,對于EXE型程序來說,Delphi會為你的程序插入其一個名稱為_InitExe的過程,而對于DLL型程序來說,Delphi編譯器會為你的程序插入一個名稱為_InitLib的過程,你可以從SysInit.pas單元的源代碼當中找到這兩個過程的定義和實現(xiàn)。說到這里順便提一句,System.pas和SysInit.pas兩個Pascal單元是Delphi編譯器在編譯程序時默認包含的兩個單元(你從來沒有見到過哪一個程序uses過這兩個單元吧)。而Delphi的每一個版本幾乎都會對這兩個單元進行擴展和修改,也正因為這個原因,所以在前面你看到的使用Delphi7編譯的那個小程序的Size要比Delphi5編譯出來的同樣程序大的多。

在_InitExe過程的內(nèi)部會調(diào)用一個名稱為_StartExe的過程,而在這個_StartExe過程的內(nèi)部中則會去調(diào)用在System.pas單元中定義的SetExceptionHandler函數(shù)來初始化整個Delphi的異常處理機制,在這個過程中設(shè)置的_ExceptionHandler過程則正是Delphi整個異常處理機制的核心處理過程。

在_ExceptionHandler會使用到System.pas單元中定義的一系列過程指針變量(比如ExceptProc,ExceptClsProc,ExceptObjProc等),這些過程指針變量都是Delphi整個異常機制當中必須的使用到的,而這些變量的初始化工作便是在SysUtils.pas單元中定義的InitExceptions單元中,InitExceptions變量會在SysUtils單元的initialization部分被調(diào)用,于是整個Delphi的異常處理機制便初始化完成。對于DLL型的程序,其異常處理過程的初始化部分與EXE型的程序一樣,所以在這里就不再復(fù)述了。

好了在介紹了Delphi最核心的異常處理過程之后,我們再來介紹一下這些異常處理過程是如何被觸發(fā)的。

當是一個異常被觸發(fā)后,操作系統(tǒng)會最先攔截到這個異常。在操作系統(tǒng)攔截到這個異常后,它會馬上調(diào)用.KiUserExceptionDispatcher函數(shù)(注1),這個函數(shù)是的Windows操作系統(tǒng)自身使用的異常處理函數(shù),而在KiUserExceptionDispathcher函數(shù)調(diào)用的過程中,它會通過某種回調(diào)機制,最終去調(diào)用我們上面提到過的_ExceptionHandler過程,展開異常并處理之,如果沒有找到如果被拋出異常所匹配的異常,那么則調(diào)用在SysUtils.pas中被賦值的ExceptHandler過程指針變量,拋出一個出現(xiàn)異常信息的話框,并在用戶按下確定按鈕之后終止程序。

這里面值得一的是,如果ExceptHandler過程指針變量的值為Nil,那么Delphi的RTL會去調(diào)用System.pas單元中定義的MapToRunError過程來做一個異常類型到運行時錯誤碼的映射,并最終調(diào)用RunErrorAt過程在顯示運行時錯誤對話框(如圖1所示)終止整個程序的運行。

注1:我的操作系統(tǒng)是WIN2K所以KiUserExceptionDispatcher在ntdll當中,由于條件有限我沒有在WIN98下做過類似的調(diào)試,不知道在WIN98下面是否也使用類似的方式來處理異常。另由于KiUserExceptionDispatcher函數(shù)微軟未文檔化的一個函數(shù),所以我在這里不太方便對此函數(shù)的運作機制進行剖析(因為不同的操作系統(tǒng)中此函數(shù)的實現(xiàn)機制可能會不同),所以在這里還請您見諒。

轉(zhuǎn)載于:https://www.cnblogs.com/temptation/archive/2006/04/25/384333.html

總結(jié)

以上是生活随笔為你收集整理的[转] 《完美程式设计指南》Effective Delphi的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。