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
以下是您在編寫代碼時應該記住的一些一般訣竅。
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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.