Отладка паники в ОС Symbian с использованием Carbide.c ++ - PullRequest
2 голосов
/ 26 августа 2010

Есть ли способ попасть в отладчик, когда любая паника возникает, как если бы была точка останова?

Я использую Carbide.c ++ 2.3.0. Я знаю об Отладочных конфигурациях> Исключения x86, но он охватывает лишь небольшую часть того, что на самом деле может произойти в реальном приложении. Например, он не улавливает панику пользователя или ALLOC при выходе из приложения с утечками памяти.

Ответы [ 2 ]

2 голосов
/ 31 августа 2010

Если вы используете эмулятор, вы можете отладить панику, включив «своевременную отладку».Это можно сделать, добавив следующую строку в epoc32\data\epoc.ini:

JustInTime debug

Для получения дополнительной информации см. Ссылку epoc.ini в документации SDK .

2 голосов
/ 27 августа 2010

Насколько я знаю, это невозможно сделать.

Что я сделал, так это использовал простую логику трассировки функций, поэтому при возникновении паники у меня возникает трассировка стека в точке паники в коде обработки паники (который я выхожу из системы). Это работает хорошо, за исключением того факта, что вы должны помнить, что нужно добавлять макросы в начале каждой функции.

, например

#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 3-го издания, я не пробовал его в более поздних версиях 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;
    }
...