Symbian真机调试技术总结
基于Symbian平台(2nd/3rd)开发的程序软件,很多人都会碰到在模拟器上运行的非常正常,但一到真机上运行,就会碰到这样那样的问题。一旦在真机上出现问题,一般情况下就不会很方便的就可以解决,这就涉及到如何调试真机程序,快速准确地定位到问题所在。
总结真机调试的经验,给出如下结论:
“使用文件系统写log,同时让真机也像模拟器那样在出现Panic的时候弹出提示框”
一.使用文件系统写日志
Symbian平台本身提供了一个写log类-RFileLogger
,该类可以很方便地将需要的日志写到文件中,但该类有局限性,在程序开发中需考虑是否使用。
1. 必须将log文件写到一定的路径中(C:/Logs)
2. 一次log写入长度有限制(KLogBufferSize=150,flogger.h
)
基于上面所列,所以在非小型程序中不推荐使用RFileLogger
类,而推荐使用一般的基于IO的写日志方法(后面附上一个简单可用的TRACE类)。
二.
在真机上弹出Panic提示框(带Panic类别及错误号)
想要在真机上也像模拟器那样,在出现Panic的时候,弹出详细的Panic类别及错误号,这对定位真机问题非常有帮助。不过该机制在Symbain S60 2nd和3rd上有不同。在Symbain S60 3rd及以上,只需在.pkg文件中的文件安装部分加上如下语句即可:
;Files to install
"ErrRd" -"!:/resource/ErrRd"
但在Symbian 2nd(不知道是否是全部2nd版本还是某些版本)上,按上述方法不能得到预期的结果(2nd FP2就是这样)。这时就需要额外软件帮助了,有个叫TaskSpy的免费软件可以用来实现我们想要的功能。
三.总结
虽然在使用Carbie C++ IDE时,可以利用TRK进行真机联机调试,但使用TRK调试的效果并不是很好,尤其是稍微复杂或者大型的软件。“使用文件系统写log,同时让真机也像模拟器那样在出现Panic的时候弹出提示框”,这个方法应该是最适合真机调试及定位问题。
附:CTraceLog类
//TraceLog.h
#ifndef TRACELOG_H
#define TRACELOG_H
// INCLUDES
#include <e32std.h>
#include <e32base.h>
#include <f32file.h>
#include <S32FILE.H>
// CLASS DECLARATION
const TInt KMaxLogSize = 4096;
/**
* CTraceLog
*
*/
class CTraceLog : public CBase
{
public:
// Constructors and destructor
/**
* Destructor.
*/
~CTraceLog();
/**
* Two-phased constructor.
*/
static CTraceLog* NewL();
/**
* Two-phased constructor.
*/
static CTraceLog* NewLC();
void OutPutlog(TUint8 aLevel,TRefByValue< const TDesC16 > aFmt,...);
void OutPutlog(TUint8 aLevel,TRefByValue< const TDesC8 > aFmt,...);
void OutPutlog(TUint8 aLevel,const char *aFmt,...);
private:
/**
* Constructor for performing 1st stage construction
*/
CTraceLog();
/**
* EPOC default constructor for performing 2nd stage construction
*/
void ConstructL();
private:
RFile iFile;
RFileWriteStream iOutputStream;
TTime iTraceTime;
TBuf<KMaxLogSize> iLogBuf16;
TBuf8<KMaxLogSize> iLogBuf8;
};
#endif // TRACELOG_H
// TraceLog.cpp
#include "TraceLog.h"
#include <COEMAIN.H>
_LIT(KTimeFormat,"%Y%M%D%1-%2-%3 %H:%T:%S");
_LIT(KLogFile,"e://logs//paysercer_log.txt");
_LIT(K16LogLevel0," <Info >: ");
_LIT(K16LogLevel1," <Error>: ");
_LIT(K16LogEOF,"/r/n");
_LIT8(K8LogLevel0," <Info >: ");
_LIT8(K8LogLevel1," <Error>: ");
_LIT8(K8LogEOF,"/r/n");
CTraceLog::CTraceLog()
{
// No implementation required
}
CTraceLog::~CTraceLog()
{
iOutputStream.Close();
iFile.Close();
iFs.Close();
}
CTraceLog* CTraceLog::NewLC()
{
CTraceLog* self = new (ELeave)CTraceLog();
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CTraceLog* CTraceLog::NewL()
{
CTraceLog* self=CTraceLog::NewLC();
CleanupStack::Pop(); // self;
return self;
}
void CTraceLog::ConstructL()
{
TInt ret;
User::LeaveIfError(iFs.Connect());
ret = iFs.MkDirAll(KLogFile);
if( (KErrNone!=ret) && (KErrAlreadyExists!=ret) )
User::Leave(ret);
User::LeaveIfError(iFile.Open(iFs,
KLogFile,
EFileWrite) );
iOutputStream.Attach(iFile);
iOutputStream.Sink()->SeekL(MStreamBuf::EWrite,EStreamEnd);
}
void CTraceLog::OutPutlog(TUint8 aLevel,TRefByValue< const TDesC16 > aFmt,...)
{
iTraceTime.HomeTime();
iTraceTime.FormatL(iLogBuf16,KTimeFormat);
if(aLevel == 0) //EInfo
iLogBuf16.Append(K16LogLevel0);
else //EError
iLogBuf16.Append(K16LogLevel1);
VA_LIST ap;
VA_START(ap,aFmt);
iLogBuf16.AppendFormatList(aFmt,ap);
VA_END(ap);
iLogBuf16.Append(K16LogEOF);
iLogBuf8.Copy(iLogBuf16);
iOutputStream.WriteL(iLogBuf8);
iOutputStream.CommitL();
}
void CTraceLog::OutPutlog(TUint8 aLevel,TRefByValue< const TDesC8 > aFmt,...)
{
iTraceTime.HomeTime();
iTraceTime.FormatL(iLogBuf16,KTimeFormat);
iLogBuf8.Copy(iLogBuf16);
if(aLevel == 0) //EInfo
iLogBuf8.Append(K8LogLevel0);
else //EError
iLogBuf8.Append(K8LogLevel1);
VA_LIST ap;
VA_START(ap,aFmt);
iLogBuf8.AppendFormatList(aFmt,ap);
VA_END(ap);
iLogBuf8.Append(K8LogEOF);
iOutputStream.WriteL(iLogBuf8);
iOutputStream.CommitL();
}
void CTraceLog::OutPutlog(TUint8 aLevel,const char *aFmt,...)
{
iTraceTime.HomeTime();
iTraceTime.FormatL(iLogBuf16,KTimeFormat);
iLogBuf8.Copy(iLogBuf16);
if(aLevel == 0) //EInfo
iLogBuf8.Append(K8LogLevel0);
else //EError
iLogBuf8.Append(K8LogLevel1);
TPtrC8 fmt((TUint8*)aFmt);
VA_LIST ap;
VA_START(ap,aFmt);
iLogBuf8.AppendFormatList(fmt,ap);
VA_END(ap);
iLogBuf8.Append(K8LogEOF);
iOutputStream.WriteL(iLogBuf8);
iOutputStream.CommitL();
}