首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用__debugbreak()尝试/捕捉

使用__debugbreak()尝试/捕捉
EN

Stack Overflow用户
提问于 2015-10-08 04:58:55
回答 1查看 2.5K关注 0票数 5

我使用的是在某些情况下运行__debugbreak()的第三方__debugbreak DLL,并且在这样做之前不检查IsDebuggerPresent()。当该场景发生在调试器之外(例如,运行应用程序的最终用户)时,这将导致我的应用程序“崩溃”。我想抓住它,自己处理,或者至少忽略它。

实际上,我已经有了一个未处理的异常过滤器来将SEH转换为C++异常一段时间,所以它不起作用有点奇怪。

代码语言:javascript
复制
::SetUnhandledExceptionFilter(OnUnhandledException);

我一直在做一些直接测试,标准的__try/__ but可以工作,因此我可以将每个调用包装到DLL中作为后盾,但是如果__try/__but有效的话,那么::SetUnhandledExceptionFilter()也应该能工作。

代码语言:javascript
复制
    __try
    {
        __debugbreak();
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        printf("caught");
    }

试/抓(.)不管用。

代码语言:javascript
复制
    try
    {
        __debugbreak();
    }
    catch (...)
    {
        printf("caught");
    }

_set_se_translator()也不起作用。

https://msdn.microsoft.com/en-us/library/ms679297(VS.85).aspx的MSDN文档中可以看出,它应该充当结构化异常。我意识到这是DebugBreak()的文档,但我也用它进行了测试,并且遇到了同样的问题,即使是“catch(.)”。

我正在用/EHa编译。

我如何捕获__debugbreak (asm 3),或者至少改变行为?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-11 21:51:34

断点生成EXCEPTION_BREAKPOINT结构化异常。您不能使用try/catch来捕获它,因为它不会被转换为C++异常,不管是/EHa开关还是_set_se_translatorEXCEPTION_BREAKPOINT是一个特殊的例外。

首先,您应该知道catch块和__except块只有在解除堆栈后才会执行。这意味着执行在处理程序块之后继续,而不是在调用__debugbreak()之后。因此,如果您只想跳过EXCEPTION_BREAKPOINT,同时在int 3指令之后继续执行。您应该使用向量异常处理程序。下面是一个示例:

代码语言:javascript
复制
// VEH is supported only on Windows XP+ and Windows Server 2003+
#define _WIN32_WINNT 0x05020000

#include <windows.h>
#include <stdio.h>

//AddVectoredExceptionHandler constants:
//CALL_FIRST means call this exception handler first;
//CALL_LAST means call this exception handler last
#define CALL_FIRST 1  
#define CALL_LAST 0

LONG WINAPI
VectoredHandlerBreakPoint(
struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
    {
        /*

        If a debugger is attached, this will never be executed.

        */

        printf("BreakPoint at 0x%x skipped.\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);

        PCONTEXT Context = ExceptionInfo->ContextRecord;

        // The breakpoint instruction is 0xCC (int 3), just one byte in size.
        // Advance to the next instruction. Otherwise, this handler will just be called ad infinitum.
#ifdef _AMD64_
        Context->Rip++;
#else
        Context->Eip++;
#endif    
        // Continue execution from the instruction at Context->Rip/Eip.
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    // IT's not a break intruction. Continue searching for an exception handler.
    return EXCEPTION_CONTINUE_SEARCH;
}

void main()
{
    // Register the vectored exception handler once.
    PVOID hVeh = AddVectoredExceptionHandler(CALL_FIRST, VectoredHandlerBreakPoint);

    if (!hVeh)
    {
        // AddVectoredExceptionHandler failed.
        // Practically, this never happens.
    }

    DebugBreak();

    // Unregister the handler.
    if (hVeh)
        RemoveVectoredExceptionHandler(hVeh);
}

这样,断点指令int 3将被跳过,下一个指令将被执行。另外,如果附加了调试器,它将为您处理EXCEPTION_BREAKPOINT

但是,如果您真的想要展开堆栈,则必须使用__except(GetExceptionCode() == EXCEPTION_BREAKPOINT ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33006974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档