C++ 如何在WinCE中捕获未处理的异常?

C++ 如何在WinCE中捕获未处理的异常?,c++,exception-handling,windows-ce,C++,Exception Handling,Windows Ce,在桌面Windows中,我可以在Windows.h中使用SetUnhandledExceptionFilter功能,但在WinCE中不起作用。如何在WinCE中捕获未处理的异常 注释:我使用C++和NET.NET.< /P> < P>我发现的唯一方法是用以下的包来封装应用程序中的每个线程的执行: __try { // Call the thread start function here } __except(MyExceptionFilter(GetExceptionInformati

在桌面Windows中,我可以在
Windows.h
中使用
SetUnhandledExceptionFilter
功能,但在WinCE中不起作用。如何在WinCE中捕获未处理的异常


注释:我使用C++和NET.NET.< /P> < P>我发现的唯一方法是用以下的包来封装应用程序中的每个线程的执行:

__try
{
    // Call the thread start function here
}
__except(MyExceptionFilter(GetExceptionInformation())
{
    // Handle the exception here
}
这听起来需要做很多工作,但如果您编写一个函数,像这样包装线程,则相对容易:

typedef struct {
    void* startFct;
    void* args;
} ThreadHookArgs;

// "params" contains an heap-allocated instance of ThreadHookArgs
// with the wrapped thread start function and its arguments.
DWORD WINAPI wrapThread(LPVOID params) {

    ThreadHookArgs threadParams;
    memcpy(&args, params, sizeof(ThreadHookArgs));

    // Delete the parameters, now we have a copy of them
    delete params;

    __try {
        // Execute the thread start function
        return ((LPTHREAD_START_ROUTINE) threadParams.startFct) (threadParams.args);
    }
    __except(MyExceptionFilter(GetExceptionInformation())
    {
        // Handle the exception here
        return EXIT_FAILURE;
    }

}
然后编写自己的线程创建函数,调用钩子而不是线程启动函数:

// Drop-in replacement for CreateThread(), executes the given
// start function in a SEH exception handler
HANDLE MyCreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
                       DWORD dwStackSize,
                       LPTHREAD_START_ROUTINE lpStartAddress,
                       LPVOID lpParameter,
                       DWORD dwCreationFlags,
                       LPDWORD lpThreadId)
{
    HANDLE hThread;
    DWORD dwThreadId;

    LPTHREAD_START_ROUTINE startFct = lpStartAddress;
    LPVOID startParam = lpParameter;

    // Allocate the hook function arguments on the heap.
    // The function will delete them when it runs.
    ThreadHookArgs* hookArgs = new ThreadHookArgs;
    hookArgs->fct = lpStartAddress;
    hookArgs->args = lpParameter;

    // Set the start function of the created thread to
    // our exception handler hook function
    startFct = (LPTHREAD_START_ROUTINE) &wrapThread;
    startParam = hookArgs;

    // Start the hook function, which will in turn execute
    // the desired thread start function
    hThread = CreateThread( lpThreadAttributes,
                            dwStackSize,
                            startFct,
                            startParam,
                            dwCreationFlags,
                            &dwThreadId );

    return hThread;
}
请注意,如果您使用的是Windows CE 6及更高版本,则这些版本已经对异常处理进行了矢量化,这可能会使异常处理变得更容易:


矢量异常处理无法解决此问题,因为在调用任何帧特定的筛选器之前调用矢量异常筛选器,而在调用所有异常筛选器之后调用未处理的异常筛选器。这是非常容易出错的,因为它会使在调用其他筛选器之前调用筛选器的许多假设无效。此解决方案的另一个问题是。如果您不完全尊重Windows CE ABI,那么基于帧的异常过滤器可能会被跳过,因为内核可能无法正确展开堆栈。请注意,即使程序不遵守Windows CE ABI,向量异常过滤器仍会被调用。事实上,我只使用向量化异常处理来捕获状态\u CRASH\u DUMP,并绕过在这种情况下得到的错误窗口,而是转储一个关于触发它的异常的日志;我也没有意识到ABI的问题,到目前为止,解决方案一直运行良好。不幸的是,似乎没有真正的通用方法来解决这个问题。