Symbian Skill

編碼訣竅

以下是您在編寫代碼時應該記住的一些一般訣竅。

1. 確保您的應用程序能夠對系統關機事件做出響應。在您的AppUi::HandleCommandL()方法中,必須要對EEikCmdExit(以及任何特定平臺相關的事件,例如Series 60 上的EAknSoftkeyBack)做出響應。

2. 要對外來系統事件做出響應。請牢記,您的應用程序是在一個多任務電話系統上運行,您需要將注意力集中於剛獲得的/丟失的事件上,以確保當用戶獲得一個高優 先級的通知時您能夠做出正確響應。例如,正打進來的電話會干擾您的應用程序的運行,這時應確保您已保存了系統狀態和數據(即:您需要對標準的“背景”事件 採取適當的行動——請參閱SDK)。一般說來,系統框架會處理這個問題,您不需要採取任何特殊行動——但一定要確保您沒有妨礙系統框架的正常操作。

3. 內存處理是Symbian OS 需要考慮的一個重要課題。在這一點上,應注意電話有時會不同於模擬器。因此在將您的應用程序呈交給“Symbian 認證簽名”進行測試之前,務必確保已在實際電話設備上測試了您的程序。

4. 內存堆棧空間有限!應儘可能將對象放到內存堆中,而不要放到棧裏。KERN-EXEC 3 異常(panic)發生的主要原因之一就是棧的破壞/溢出。

5. 應用程序發生異常(panic) 表明您的代碼中一定有錯誤。以下是一些主要、常見的錯誤:

• 忘記將非對象成員、被分配到堆的變量加到CleanupStack 上。

• 將成員變量放到CleanupStack 上——這一點要千萬避免;在析構函數中將這些變量刪除就可以了。

• ‘重複刪除’——例如,沒有正確的從CleanupStack上Pop()出已經被銷燬的對象,造成CleanupStack以後試圖再次刪除它。或者使用過一個對象之後將其刪除但忘記將其值設成NULL,從而在析構函數又試圖刪除一次。

• 用可能不存在於您的析構函數中的變量調用函數。

例如,以下代碼可能導致異常,因爲有可能您在分配內存之前您的對象已經被銷燬,或者在應用程序的另一處已經刪除了該內存,這樣iSomeServer 就會處於NULL:

CMyClass::~CMyClass()

{

iSomeServer->Close();

delete iSomeServer;

}

應該如下編寫代碼:

CMyClass::~CMyClass()

{

if (iSomeServer)

{

iSomeServer->Close();

delete iSomeServer;

}

}

• 在NULL 指針上調用函數。

• 函數調用另一個函數,而其使用的變量已經超出範疇,

例如:把一個棧變量傳送到一個異步函數的回調(callback) 裏。在系統資源不夠的情況下,得體的處理失效情況是非常重要的。最受限制的資源通常是系統RAM,因此您需要注意正確的處理內存不足的情況。採用‘兩段構 造方法’和如下所述的CleanupStack 機制,對這種防禦性編程來說是必不可少和極其重要的。

7. 對帶“R”字頭、具備Close()方法的類,總是使用CleanupClosePushL()。這將確保當Leave 事件發生時,它們會被恰當的清除。例如:

RFile file;

User::LeaveIfError(file.Open(…));

CleanupClosePushL(file);



CleanupStack::PopAndDestroy(&file);

對用Release()或Destroy()的‘R’ 類,亦可使用

CleanupDeletePushL()及

CleanupReleasePushL()來取代Close()。

8. 另外,請記住CleanupStack 機制是可擴展的,面對所有Leave 事件,都可以用它來有效的清除任何對象。即使您需要處理的是較複雜的情況,也不應該忽略採用正規的清理機制。欲進一步瞭解TCleanupItem,請參 閱Symbian OS Library 文檔。

9. 倘若您意圖對HBufC 變量重新分配資源,在清除它們之後,總是將其設爲NULL。由於HBufC 的資源分配或其再分配可能會導致Leave 事件的發生,從而可能會出現析構函數試圖刪除已經不存在的HBufC變量的情況。當然,對於任何由堆分配資源的變量而言都應如此,對HBufC 變量採取此做法更是已經成爲普遍的使用模式。

10. 當必須採用自己的TRAP 時,請勿忽略所有的報錯。

常見的編碼錯誤是:

TRAPD(err, DoSomethingL());

if (err == KErrNone || err ==KErrNotFound)

{

// Do something else

}

這意味着其他錯誤碼都被忽略。然而,倘若您非用上述模式不可,應採用Leave 機制來處理其他錯誤:

TRAPD(err, DoSomethingL());

if (err == KErrNone || err ==KErrNotFound)

{

// Do something else

}

else

User::Leave(err);

11. 不要延誤將對象PushL()到CleanupStack 上。所有新創建的對象(成員變量除外)應被立即壓入該堆

棧。例如,下面的作法是錯的:

void doExampleL()

{

CSomeObject* myObject1=new (ELeave)CSomeObject;

CSomeObject* myObject2=new (ELeave)CSomeObject;…

// Do something here with thevariables

CleanupStack::PushL(myObject1);

CleanupStack::PushL(myObject2);

// Do something more with the variables…

CleanupStack::PopAndDestroy(2);

// myObject2, myObject1

}

因爲myObject2 的創建可能失敗,造成myObject1“懸”在那裏不能被清理。應該這樣來實現:

void doExampleL()

{

CSomeObject* myObject1=new (ELeave)CSomeObject;

CleanupStack::PushL(myObject1);

CSomeObject* myObject2=new (ELeave)CSomeObject;

CleanupStack::PushL(myObject2);



// Do something here with the variables…

CleanupStack::PopAndDestroy(2);

// myObject2, myObject1

}

12. 注意,那些名稱有大寫字母C 結尾的函數(例如NewLC())會自動把其對象置於CleanupStack。您不應該自己來將這些對象壓入CleanupStack,否則該對象會入棧兩次。當您創建非成員變量併爲其分配內存時,這些由C 結尾的函數很有用。

13.“兩段構造方法”是Symbian OS 內存管理的關鍵部分。基本原則是Symbian OS 中的構造函數或析構函數永遠不應該發生Leave。倘若一個C++ 構造函數Leave,構造過程未完成的對象得不到清理,因爲還沒有生成指針指向該對象。爲此,SymbianOS 中的構造函數僅將該對象實例化,而後調用該對象的ConstructL()函數,在其中將成員數據實例化。一旦ConstructL()發生Leave, 標準的析構函數將被調用來清除所有至此已被成功分配的成員變量。在您的編碼中照用這一設計模式來防止內存泄漏,至爲關鍵。當您寫每一行代碼時,都應該問自 己:“ 這一行代碼能否發生Leave ?”假如回答爲“是”,則應考慮“是否所有資源都將被釋放?”。

14. 編碼中請勿使用_L()宏——而應使用_LIT()。_L()自Symbian OS v5 起已是‘不推薦使用’(deprecated),它的問題在於它將調用TPtrC(const TText*)構造函數,該構造函數會調用strlen()函數來計算該字串的長度。雖然這不會帶來額外的RAM 開銷,卻會在運行時佔用更多CPU 週期。相反,宏_LIT()直接創建了一個在編譯時就全部實例化的對象,節省了構造TPtrC 的CPU 開銷。當然,您首先應該考慮的是否應該使用硬編碼的字符串常量,因爲當您將來地方化(localize)您的程序時,這種常量類型的描述符

(descriptor) 可能需要重新編碼。

15. 當在函數參數中使用描述符(descriptor) 時,應缺省使用基類。在大多數情況下,以const TDesC& 形

式來傳遞描述符。對可修改的描述符,則應使用TDes&。

16. 當在函數中傳遞或返回對象時,應確保如果您擁有該對象的所有權,您應負責將其清除! Symbian 採取的約定是:函數中的指針表示所有權轉移到調用者,而使用引用則表示被傳遞對象的所有權仍屬於原所

有者。

17. Active Objects 是Symbian OS 的重要特性之一。請仔細研究SDK 文檔、Symbian Developer Network 白皮書,以充分理解其工作原理。下面是一些有用的竅門:

• 在RunL()內無需使用TRAP()。Active Scheduler本身會TRAP 函數RunL()並在其發生Leave 時調用CActive::RunError()。• 爲此,您應實現自己的RunError()函數來處理從RunL()的Leave 事件。

• 保證RunL()操作儘可能簡短。長時間運行的RunL()將阻塞其他Active Objects。

• 總是實現DoCancel()函數,總是在AO 析構函數中調用Cancel()。

18. 您應儘可能利用Active Object 框架機制。對於使用電池供電的設備,在一個循環中緊密不斷地進行輪流檢測(polling) 是極其不適當的,將帶來大量耗電。寫遊戲時,對此尤需特別注意,詳情參閱Symbian

Developer Network 網站的技術文檔(www.symbian.com/developer/techlib/papers/porting_3D_games/XenGames_paper.pdf)。

19. ViewSrv 11 異常對於繁忙運行的程序(例如遊戲)是一個潛在的問題。當您的,或者其他任何程序中的ViewSrv active object 不能及時響應View Server 時就會導致此種異常。典型的最長迴應時間是10-20 秒。FAQ-0900 有詳細解釋,FAQ-0920 有針對如何避免此類問題的實用技巧。二者均可從www3.symbian.com/faq.nsf 網頁上的Symbian OSFAQ 數據庫獲取。

20. 您無需使用HBufC::Des()來進入一個HBufC 對象。只需採用* 操作符來爲HBufC 對象解除引用(dereference)。這對於向某個接受TDesC&(上文的推薦做法)的函數傳遞HBufC 參數時尤其有用。

21. 當使用標準的程序.INI 文件的功能時,(即在您的應用UI 類中使用Application()->OpenIniFileLC();API 時),確保將版本號信息寫入流(stream) 中。這樣使您能夠在未來新版本的程序中建立新的流,意味着即使某個最終用戶將來安裝您的軟件的新版本時,不會因爲在舊的.INI 文件中找不到正確配置或流時發生異常。

22. 在您的程序中實現框架類(framework class) 時要小心。應該始終從所提供的平臺相關的框架類中繼承。例如,對UIQ 而言,不要從CEikAppUi 繼承您的AppUi 類,而應從CQikAppUi 繼承。所有的應用基類(CQikAppUi、CQikApplication、CQikDocument)添加的功能支持更廣的框架範圍來保證應用程序正 確運行。

測試訣竅

1. 最重要的測試訣竅是,在用模擬器時(emulator),正確的退出您的程序,而不是僅僅簡單地關閉整個模擬器。在調試模式中,在應用程序框架(applicationframework)的關閉函數前後有內存及句柄檢測代碼,

當您退出應用程序時,此代碼將被調用,從而可檢測到是否有內存泄漏或遺留句柄(例如R 對象)發生。

對UIQ 程序而言,爲此目的習慣上在調試模式裏提供一個Exit 菜單選項。

2. 另外一個至關重要的訣竅是在發佈您的程序之前確保在.PKG 文件中包含了正確的平臺相關信息。相關平臺相關信息字符串的詳情請參照該平臺的SDK。www3.symbian.com/faq.nsf 上的Symbian OS FAQ 數

據庫中的FAQ-0853 提供了有用的相關信息。

3. 在寫.PKG 文件時,也要確保恰當的使用了“!:/”語法。一般來說,您的應用程序應可從最終用戶手機中的任何盤中安裝、運行。僅有極少量的文件需要放置於C:/ 盤中(例如.INI 文件)。

調試訣竅

1. 總應先使用模擬器調試;大部分同時發生在模擬器與硬件上的問題,使用模擬器調試會容易得多。

2. 在編寫和調試新的控制類時,把iEikonEnv->WsSession().SetAutoFlush(ETrue)置於您的AppUi 的ConstructL()函數中。這意味着gc draw 指令會在模擬器中立即顯示,而不是在下一次沖刷(flush)視窗服務器客戶端緩衝時。編輯WSINI.INI 文件(/epoc32/release/winscw/udeb/system/data/),確保不存在關鍵字FLICKERFREEREDRAW。這 意味着您可以逐步運行draw 代碼,並看到每行代碼的效果。然而,應確保此行代碼不留在發佈的軟件中,因爲這會影響性能。

3. 應定時對源文件運行LeaveScan 工具。該工具可以檢測到所有可以Leave 的函數,並在其名稱不以L 結尾時報錯,並提醒源文件中潛在的缺陷或疏忽。在檢查哪些代碼應被允許Leave,並確保已正確處理此狀況時,該工具非常有效。參見 www3.symbian.com/faq.nsf 上的Symbian OS FAQ 數據庫裏的FAQ-0291,下載該工具並進一步瞭解。

4. 如果您的程序在正常關閉時因內存泄漏而發生異常,在MS Visual Studio 中可將泄漏的地址轉換爲CBase*類型,從而查看該泄漏對象的類型。

5. 最近爲對Symbian OS 開發者提供了新的功能:設備上調試(on-target debugging)。雖然不是所有的SDK及工具均已具備此功能,但大多數最近發佈的SDK 及IDE 支持此功能。如可使用此功能,請在發佈您的程序前使用它來檢測任何潛在的手機硬件相關的缺陷。進一步的信息,請閱讀SDK 及IDE 文檔。

6. 確保‘Just in Time’調試被啓用:

• 確保在文件“/epoc32/data/epoc.ini”裏刪除了宏“JustInTime 0”

• 註冊表值做如下設定:

[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug]"UserDebuggerHotKey"=dword:00000000"Debugger"="/"C://apps//Metrowerks//bin//IDE.exe/" -p %ld -e %ld""Auto"="0"20

7. 審閱%Temp%epocwind.out 所含的糾錯訊息。

8. 使用所有可用的開發工具,包括Lint、Leavesan、HookLogger、Panix、D_EXC 來檢查內存泄漏及其他錯誤。這些工具及其他更多有用的工具可在SymbianDeveloper Network 下載(www.symbian.com/developer/downloads/tools.html)。

9. FAQ-1344 教您如何診斷並調試違反平臺安全(KErrPermissionDenied) 的故障,這有助於識別您的程序所缺少的權限(capability)。

參考讀物

[1] Symbian Developer Network newsletter

http://www.symbian.com/developer/faq/index.html

[2] Symbian OS FAQ database

http://www.symbian.com/developer/techlib/faq.html

[3] Symbian OS C++ Coding Standards paper

http://www.symbian.com/developer/techlib/papers/coding_stds/2003-01_SyOSCodStn.pdf#one

[4] Coding Idioms paper

http://www.symbian.com/developer/techlib/papers/coding_idioms/2002_10_09_codingSymbianOS.pdf

[5] Symbian Press

http://www.symbian.com/developer/books

[6] Games Writing paper

http://www.symbian.com/developer/techlib/papers/porting_3D_games/XenGames_paper.pdf

[7] Active Objects paper

http://nds2.ncsp.nokia.com/download/?asset_id=11981;ref=symbian

or http://www.forum.nokia.com/main/1,,1_32_10_5,00.html

開發者資源

Symbian Developer Network

http://www.symbian.com/developer

Symbian Developer Network Newsletter

http://www.symbian.com/developer/newsletter.html

Symbian OS Tools Providers

http://www.symbian.com/developer/downloads/tools_providers.html

Sony Ericsson Developer World

http://developer.sonyericsson.com/site/znch/home/p_home.jsp

Forum Nokia

http://forum.nokia.com

Sun Microsystems Developer Services

http://gceclub.sun.com.cn/NASApp/sme/controller/teclist?tid=01
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章