Отладка паники в ОС Symbian с помощью Carbide.c ++
Вопрос
Есть ли способ бросить в отладчик, когда Любые Паника возникает, как если бы была точка останова?
Я использую Carbide.c ++ 2.3.0. Я знаю о отладочных конфигурациях> x86 Исключения, но он охватывает только небольшую долю тому, что может произойти в реальном применении. Например, он не ловит панику пользователя или паникулы Alloc, когда приложение выходит с утечками памяти.
Решение
Если вы используете эмулятор, вы можете отлаживать паникулы, позволяя «отладку» сразу же отладки. Это делается, добавив следующую строку в epoc32\data\epoc.ini
:
JustInTime debug
Для получения более подробной информации см. Ссылка EPOC.INI в документации SDK.
Другие советы
Насколько мне известно, это не может быть сделано.
То, что я сделал, это используйте простую логику отслеживания функций, поэтому, когда паника произойдет, у меня есть след стека в точке паники в моем коду обработки паники (который я выхожу на выход). Это хорошо работает, кроме того, что вам нужно помнить, чтобы добавить свой макрос в начале каждой функции.
например
#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 у меня было много успеха с Логигер крюка под эмулятором. Это настоящая боль для настройки и использования, но это будет очень легко отслеживать утечки памяти 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;
}