热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Symbian调试技术

Symbian调试技术模拟器不显示Panic细节若Panic发生了,除非在指定的位置有一个名叫“ErrRd”的文件,否则模拟器不显示Panic的细节。

Symbian调试技术


  • == 模拟器不显示Panic细节 ==  

若Panic发生了,除非在指定的位置有一个名叫“ErrRd”的文件,否则模拟器不显示Panic的细节。这使得很难知道是什么引起Panic。

在SDK 3rd版以前,ErrRd文件必须手工创建,但从3rd版以后,这个文件可以默认在目录“C:/Symbian/9.2/S60_3rd_FP1/Epoc32/winscw/c/resource”下找到。有了ErrRd,Panic发生时的输出像这样:

''提示: 如果即使使用3rd版的SDK,ErrRd文件也找不到,那就启动模拟器,选择 Tools > Preferences'',然后勾上Extended panic code file。


  • == 使用断言检测Bug ==

使用断言检测所做的“代码是正确的”的假设,例如: 对象的状态,期望的函数参数和返回值等。Symbian OS中定义了两个断言宏: __ASSERT_ALWAYS 和__ASSERT_DEBUG。它们之间的区别是__ASSERT_DEBUG不会影响产品代码而__ASSERT_ALWAYS会。

这是一个如何使用__ASSERT_DEBUG宏的例子:


view plaincopy to clipboardprint?
  1. void TestValue(TInt aValue)   
  2. {   
  3.   _LIT(KPanicCategory, "TestValue");   
  4.   __ASSERT_DEBUG((aValue >= 0), User::Panic(KPanicCategory, 99));   
  5.   // Do something with aValue   
  6.   // ...   
  7. }  

void TestValue(TInt aValue)
{
_LIT(KPanicCategory, "TestValue");
__ASSERT_DEBUG((aValue >= 0), User::Panic(KPanicCategory, 99));
// Do something with aValue
// ...
}

上例中,如果参数aValue小于0,抛出"Panic -99"。

''注: 断言宏默认不抛Panic, 允许你来决定断言失败时调用什么过程。尽管如此,这种情况下你应该总是抛出Panic而不是返回错误或Leave。''

因为上例使用__ASSERT_DEBUG宏,只在debug编译时才检测aValue。如果有必要在产品代码中也检测参数,就应当用__ASSERT_ALWAYS。

当你不希望外部调用者需要跟踪Panic时,使用__ASSERT_DEBUG的一个替代品: ASSERT宏。ASSERT完全象是断言宏,除了它不要要你提供panic类别或描述符。

这里是该宏的定义,来自e32def.h文件:


view plaincopy to clipboardprint?
  1. #define ASSERT(x) __ASSERT_DEBUG(x, User::Invariant())  

#define ASSERT(x) __ASSERT_DEBUG(x, User::Invariant())

这是一个如何使用ASSERT宏的例子:


view plaincopy to clipboardprint?
  1. void TestValue(TInt aValue)   
  2. {   
  3.   ASSERT(aValue >= 0);   
  4.   // Do something with aValue   
  5.   // ...   
  6. }  

void TestValue(TInt aValue)
{
ASSERT(aValue >= 0);
// Do something with aValue
// ...
}

  • == 使用__UHEAP_MARK和__UHEAP_MARKEND宏检测内存泄漏 ==

检测你的代码正确地管理堆内存(换言之,不泄漏内存)的一个可能性是使用__UHEAP_MARK和__UHEAP_MARKEND宏。


view plaincopy to clipboardprint?
  1. GLDEF_C TInt E32Main()   
  2. {   
  3.   // Start checking memory leaks   
  4.   __UHEAP_MARK;   
  5.   
  6.   // Create a fixed-length, flat array, which contains 10 integers   
  7.   CArrayFixFlat* fixFlatArray;   
  8.   fixFlatArray = new(ELeave) CArrayFixFlat(10);   
  9.   // Array is not deleted, so memory will leak   
  10.   
  11.   // Stop checking memory leaks and cause a panic if there is a leak   
  12.   __UHEAP_MARKEND;   
  13.   
  14.   return KErrNone;   
  15. }  

GLDEF_C TInt E32Main()
{
// Start checking memory leaks
__UHEAP_MARK;
// Create a fixed-length, flat array, which contains 10 integers
CArrayFixFlat* fixFlatArray;
fixFlatArray = new(ELeave) CArrayFixFlat(10);
// Array is not deleted, so memory will leak
// Stop checking memory leaks and cause a panic if there is a leak
__UHEAP_MARKEND;
return KErrNone;
}

由于数据未被删除和内存泄漏检测宏,上例代码在应用程序关闭时将引起一个Panic,如下图所示:

值得一提的是堆检测宏只编译进debug版,因此可以安全地留在产品代码中而不会影响代码的大小或速度。


  • == 对象不变性宏 ==

有两个宏允许你检查对象的状态: __DECLARE_TEST 和 __TEST_INVARIANT。在实践中,它们被用来使程序员先创建一个不变性测试函数,然后在需要检测对象状态的函数的开头和结尾调用之,这是典型的做法。


view plaincopy to clipboardprint?
  1. class CLivingPerson : public CBase   
  2. {   
  3. public:   
  4.   enum TGender {EMale, EFemale};   
  5. public:   
  6.   CLivingPerson(TGender aGender);   
  7.   ~CLivingPerson();   
  8. public:   
  9.   void SetAge(const TInt aAge);   
  10. private:   
  11.   TGender iGender;   
  12.   TInt iAgeInYears;   
  13.   __DECLARE_TEST;  // Object invariance testing   
  14. };   
  15.   
  16. CLivingPerson::CLivingPerson(TGender aGender) : iGender(aGender) {}   
  17. CLivingPerson::~CLivingPerson() {}   
  18.   
  19. void CLivingPerson::SetAge(const TInt aAge)   
  20. {   
  21.   // Set age and check object invariance   
  22.   __TEST_INVARIANT;   
  23.   iAgeInYears = aAge;   
  24.   __TEST_INVARIANT;   
  25. }   
  26.   
  27. void CLivingPerson::__DbgTestInvariant() const  
  28. {  
  29.   #ifdef _DEBUG  // Built into debug code only   
  30.   // Person should be either male or female   
  31.   ASSERT((iGender == EMale) || (iGender == EFemale));   
  32.      
  33.   // Person's age shouldn't be negative   
  34.   ASSERT(iAgeInYears >= 0);  
  35.   #endif   
  36. }  

class CLivingPerson : public CBase
{
public:
enum TGender {EMale, EFemale};
public:
CLivingPerson(TGender aGender);
~CLivingPerson();
public:
void SetAge(const TInt aAge);
private:
TGender iGender;
TInt iAgeInYears;
__DECLARE_TEST; // Object invariance testing
};
CLivingPerson::CLivingPerson(TGender aGender) : iGender(aGender) {}
CLivingPerson::~CLivingPerson() {}
void CLivingPerson::SetAge(const TInt aAge)
{
// Set age and check object invariance
__TEST_INVARIANT;
iAgeInYears = aAge;
__TEST_INVARIANT;
}
void CLivingPerson::__DbgTestInvariant() const
{
#ifdef _DEBUG // Built into debug code only
// Person should be either male or female
ASSERT((iGender == EMale) || (iGender == EFemale));
// Person's age shouldn't be negative
ASSERT(iAgeInYears >= 0);
#endif
}

由于上例使用ASSERT宏,若对象状态不正确时就抛出"USER 0"Panic。


  • == 用期望的弹出项检测清除栈的不正确使用 ==

清除栈中的对象在不再有机会被Leave成孤儿时应被弹出。因此,弹出通常恰好发生在对象被删除之前。一般使用PopAndDestroy函数代替Pop函数,因为它确保对象一弹出就被删除,避免了内存泄漏的可能性。CleanupStack::Pop 和 CleanupStack::PopAndDestroy都有一个重载版本,允许调用者声明“期望的弹出项”,指明该项应从栈中弹出。在期望的弹出项不匹配所弹出的项时,将抛出"E32USER-CBase 90" Painc。推荐使用这两个重载版本,因为它们帮助检测清除栈的不正确使用。


view plaincopy to clipboardprint?
  1. CClass* obj = new(ELeave) CClass;   
  2. CleanupStack::PushL(obj);   
  3. // ...   
  4. CleanupStack::PopAndDestroy(obj);  // Panics if ‘obj’ not on top  

CClass* obj = new(ELeave) CClass;
CleanupStack::PushL(obj);
// ...
CleanupStack::PopAndDestroy(obj); // Panics if ‘obj’ not on top

''注: 在发行版编译时,期望弹出项的检测将被禁用,因此使用它们在二进制大小和效率方面都不会影响发行版编译。''


    • == 相关链接 ==



  1. Debugging techniques
  2. 调试技术

转贴:http://wiki.forum.nokia.com/index.php/%E8%B0%83%E8%AF%95%E6%8A%80%E6%9C%AF


推荐阅读
  • 字符串学习时间:1.5W(“W”周,下同)知识点checkliststrlen()函数的返回值是什么类型的?字 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 全局变量与常量在内存中的布局分析及应用
    本文详细探讨了全局变量与常量在内存中的存储布局及其应用。通过分析不同编译器和操作系统对全局变量与常量的处理方式,揭示了它们在内存中的具体分配机制。此外,文章还讨论了这些布局对程序性能和安全的影响,并提供了优化建议,帮助开发者更好地理解和利用全局变量与常量的内存管理。 ... [详细]
  • 如何撰写适应变化的高效代码:策略与实践
    编写高质量且适应变化的代码是每位程序员的追求。优质代码的关键在于其可维护性和可扩展性。本文将从面向对象编程的角度出发,探讨实现这一目标的具体策略与实践方法,帮助开发者提升代码效率和灵活性。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 本文介绍了如何利用HTTP隧道技术在受限网络环境中绕过IDS和防火墙等安全设备,实现RDP端口的暴力破解攻击。文章详细描述了部署过程、攻击实施及流量分析,旨在提升网络安全意识。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 本文将详细介绍如何在Mac上安装Jupyter Notebook,并提供一些常见的问题解决方法。通过这些步骤,您将能够顺利地在Mac上运行Jupyter Notebook。 ... [详细]
  • 解决 Windows Server 2016 网络连接问题
    本文详细介绍了如何解决 Windows Server 2016 在使用无线网络 (WLAN) 和有线网络 (以太网) 时遇到的连接问题。包括添加必要的功能和安装正确的驱动程序。 ... [详细]
  • 视频编码涉及多个关键参数,如比特率、帧率和采样率等。比特率(Bit Rate)是指单位时间内视频或音频文件的数据传输量,通常以千比特每秒(Kbps)为单位。这些参数对视频质量和文件大小有重要影响。帧率(Frame Rate)表示每秒钟显示的图像帧数,而采样率(Sample Rate)则指每秒从连续信号中提取并形成离散信号的次数。了解这些基础概念有助于更好地优化视频编码效果。 ... [详细]
  • OpenAI首席执行官Sam Altman展望:人工智能的未来发展方向与挑战
    OpenAI首席执行官Sam Altman展望:人工智能的未来发展方向与挑战 ... [详细]
author-avatar
嘉娜杰_877
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有