使用 Carbide.c++ 调试 Symbian 操作系统中的恐慌

发布于 2024-09-15 18:39:06 字数 157 浏览 11 评论 0原文

当发生任何恐慌(例如存在断点)时,有没有办法进入调试器?

我正在使用 Carbide.c++ 2.3.0。我知道调试配置> x86 例外,但它只涵盖了实际应用程序中实际发生的一小部分。例如,当应用程序因内存泄漏而退出时,它不会捕获用户恐慌或 ALLOC 恐慌。

Is there a way to drop into the debugger when any panic occurs like if there were a breakpoint?

I'm using Carbide.c++ 2.3.0. I know about the Debug Configurations > x86 Exceptions, but it covers only a small fraction of what can actually happen in a real application. For instance, it does not trap user panics, or ALLOC panics when application exits with memory leaks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

层林尽染 2024-09-22 18:39:07

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

JustInTime debug

有关更多详细信息,请参阅 epoc.ini 参考软件开发工具包文档

If you are using the emulator, you can debug panics by enabling 'just-in-time debugging. This is done by adding the following line to epoc32\data\epoc.ini:

JustInTime debug

For more details, see the epoc.ini reference in the SDK documentation.

清风疏影 2024-09-22 18:39:07

据我所知这是不可能的。

我所做的是使用简单的函数跟踪逻辑,因此当发生恐慌时,我在恐慌处理代码(我注销)中的恐慌点有一个堆栈跟踪。除了您必须记住在每个函数的开头添加宏之外,这种方法效果很好。

例如

#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;
    }

To the best of my knowledge it can't be done.

What I've done is use simple function tracing logic so when a panic happens I have a stack trace at the point of the panic in my the panic handling code (which I log out). This works well except for the fact that you have to remember to add your macro's at the beginning of every function.

e.g.

#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();
    ...
}

For ALLOC's, I've had a lot of success with the Hook Logger under the emulator. It's a real pain to setup and use but it will make it real easy to track down ALLOC memory leaks.

UPDATE: As requested, here is what my panic handling code looks like. Note that my application has to run in the background all the time, so it's setup to restart the app when something bad happens. Also this code works for 3rd Edition SDK's, I haven't tried it on later versions of the SDK's.

The point is to run the main application in another thread and then wait for it to exit. Then check to see why the thread exits, it the thread as exited for unknown reasons, log stuff like my own stack trace and restart the application.

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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文