2010-08-26 45 views
2

有没有办法让任何恐慌发生,如有断点一样掉进调试器?使用Carbide.c调试Symbian OS中的恐慌使用Carbide.C++

我正在使用Carbide.C++ 2.3.0。我了解“调试配置”>“x86异常”,但它仅涵盖实际应用程序中实际发生的一小部分内容。例如,它不会陷入用户恐慌,或者当应用程序退出时发生内存泄漏,ALLOC恐慌。

回答

2

如果您使用模拟器,您可以通过启用“即时调试”来调试恐慌。这是通过添加以下行epoc32\data\epoc.ini完成:

JustInTime debug 

有关详细信息,请参阅epoc.ini reference in the SDK documentation

+0

令人惊叹的,它真的有用! 我一直在想,Symbian工具和文档是多么模糊。确定恐慌发生的位置是非常重要的任务,但没有人知道如何去做!即使现在当你指向我的文档时,也没有任何迹象表明JustInTime选项与恐慌诱捕有关。 非常感谢! – SnakE 2010-09-01 12:59:05

+0

@SnakE:真的,该epoc.ini关键字的文档不是很清楚。那些实际上由于'JustInTime debug','User :: SetJustInTime(TBool)'而被调用的用户库函数会更好一些。 – 2010-09-01 15:24:16

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内存泄漏。

更新:根据要求,这是我的恐慌处理代码的样子。请注意,我的应用程序必须始终在后台运行,所以它设置为在发生问题时重新启动应用程序。此代码适用于第三版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; 
    } 
+0

这里最有趣的部分是你的“恐慌处理代码”,你似乎省略了。 ;)如果代码中发生任何恐慌,它确实可以做一些有用的事情。 并感谢钩记录器指针。这可能会非常方便。 – SnakE 2010-08-30 11:19:36

+0

恐慌处理代码没有什么特别之处。我会用我的恐慌处理代码更新答案。 – 2010-08-30 19:12:58

+0

感谢您的更新。单独的线程技巧非常好。我认为你的解决方案在生产环境中是不可或缺的,因为你希望避免严重的错误。 – SnakE 2010-09-01 13:12:36