使用 Carbide.c++ 在 Symbian OS 中调试恐慌
Posted
技术标签:
【中文标题】使用 Carbide.c++ 在 Symbian OS 中调试恐慌【英文标题】:Debugging panics in Symbian OS using Carbide.c++ 【发布时间】:2010-08-26 13:13:17 【问题描述】:当任何恐慌发生时,有没有办法进入调试器,就像有断点一样?
我正在使用 Carbide.c++ 2.3.0。我知道 Debug Configurations > x86 Exceptions,但它只涵盖了实际应用程序中实际发生的一小部分。例如,当应用程序因内存泄漏而退出时,它不会捕获用户恐慌或 ALLOC 恐慌。
【问题讨论】:
【参考方案1】:如果您使用的是模拟器,您可以通过启用“即时调试”来调试恐慌。这是通过将以下行添加到epoc32\data\epoc.ini
来完成的:
JustInTime debug
更多详情,请参阅epoc.ini reference in the SDK documentation。
【讨论】:
太棒了,它真的有效!我一直想知道 Symbian 工具和文档有多么晦涩难懂。确定恐慌发生在哪里是一项至关重要的任务,但没有人知道如何去做!即使现在当你指给我看文档时,也没有迹象表明 JustInTime 选项与恐慌陷阱有关。非常感谢! @SnakE:是的,那个 epoc.ini 关键字的文档不是很清楚。那些实际上被JustInTime debug
、User::SetJustInTime(TBool)
调用的用户库函数要好一些。【参考方案2】:
据我所知,这是不可能的。
我所做的是使用简单的函数跟踪逻辑,因此当发生恐慌时,我的恐慌处理代码(我注销)中的恐慌点有一个堆栈跟踪。这很好用,只是您必须记住在每个函数的开头添加宏。
例如
#ifndef NDEBUG
class __FTrace
__FTrace(const char* function)
TraceManager::GetInstance().EnterFunction(function);
~__FTrace()
TraceManager::GetInstance().LeaveFunction(function);
;
#define FTRACE() __FTrace(__PRETTY_FUNCTION__)
#else
#define FTRACE()
#endif
void Func()
FTRACE();
...
对于ALLOC,我在模拟器下使用Hook Logger 取得了很大的成功。设置和使用确实很痛苦,但它会让追踪 ALLOC 内存泄漏变得非常容易。
更新:根据要求,这是我的恐慌处理代码的样子。请注意,我的应用程序必须一直在后台运行,因此设置为在发生不良情况时重新启动应用程序。此代码也适用于第 3 版 SDK,我还没有在更高版本的 SDK 上尝试过。
关键是在另一个线程中运行主应用程序,然后等待它退出。然后检查线程退出的原因,线程由于未知原因退出,记录我自己的堆栈跟踪等内容并重新启动应用程序。
TInt StartMainThread(TAny*)
FTRACE();
__LOGSTR_TOFILE("Main Thread Start");
TInt result(KErrNone);
TRAPD(err, result = EikStart::RunApplication(NewApplication));
if(KErrNone != err || KErrNone != result )
__LOGSTR_TOFILE("EikStart::RunApplication error: trap(%d), %d", err, result);
__LOGSTR_TOFILE("Main Thread End");
return result;
const TInt KMainThreadToLiveInSeconds = 10;
// namespace *unnamed*
LOCAL_C CApaApplication* NewApplication()
FTRACE();
return new CMainApplication;
GLDEF_C TInt E32Main()
#ifdef NDEBUG
__LOGSTR_TOFILE("Application Start (release)");
#else
__LOGSTR_TOFILE("Application Start (debug)");
#endif
#ifndef NO_TRACING
__TraceManager::NewL();
#endif // !NO_TRACING
RHeap& heap(User::Heap());
TInt heapsize=heap.MaxLength();
TInt exitReason(KErrNone);
TTime timeToLive;
timeToLive.UniversalTime();
timeToLive += TTimeIntervalSeconds(KMainThreadToLiveInSeconds);
LManagedHandle<RThread> mainThread;
TInt err = mainThread->Create(_L("Main Thread"), StartMainThread, KDefaultStackSize, KMinHeapSize, heapsize, NULL);
if (KErrNone != err)
__LOGSTR_TOFILE("MainThread failed : %d", err);
return err;
mainThread->SetPriority(EPriorityNormal);
TRequestStatus status;
mainThread->Logon(status);
mainThread->Resume();
User::WaitForRequest(status);
exitReason = mainThread->ExitReason();
TExitCategoryName category(mainThread->ExitCategory());
switch(mainThread->ExitType())
case EExitKill:
__LOGSTR_TOFILE("ExitKill : (%S) : %d", &category, exitReason);
break;
case EExitTerminate:
__LOGSTR_TOFILE("ExitTerminate : (%S) : %d", &category, exitReason);
break;
case EExitPanic:
__LOGSTR_TOFILE("ExitPanic : (%S) : %d", &category, exitReason);
break;
default:
__LOGSTR_TOFILE("ExitUnknown : (%S) : %d", &category, exitReason);
break;
#ifndef NO_TRACING
__TraceManager::GetInstance().LogStackTrace();
#endif // NO_TRACING
if( KErrNone != status.Int() )
TTime now;
now.UniversalTime();
if (timeToLive > now)
TTimeIntervalMicroSeconds diff = timeToLive.MicroSecondsFrom(now);
__LOGSTR_TOFILE("Exiting due to TTL : (%Lu)", diff.Int64());
else
RProcess current;
RProcess restart;
err = restart.Create(current.FileName(), _L(""));
if( KErrNone == err )
__LOGSTR_TOFILE("Restarting...");
restart.Resume();
return KErrNone;
else
__LOGSTR_TOFILE("Failed to start app: %d", err);
__LOGSTR_TOFILE("Application End");
return exitReason;
【讨论】:
这里最有趣的部分是您似乎忽略的“紧急处理代码”。 ;) 那就是当你的代码发生任何恐慌时它真的可以做一些有用的事情。并感谢 Hook Logger 指针。这可能会派上用场。 恐慌处理代码没有什么特别之处。我会用我的恐慌处理代码更新答案。 感谢您的更新。单独的线程技巧非常好。我认为你的解决方案在生产环境中是必不可少的,在生产环境中你要确保不会出现严重的错误。以上是关于使用 Carbide.c++ 在 Symbian OS 中调试恐慌的主要内容,如果未能解决你的问题,请参考以下文章
Symbian^3 设备上的 QtWebKit 4.7.2 问题