2010-08-26 86 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