gpt4 book ai didi

c++ - 使用 __debugbreak() 尝试/捕获

转载 作者:搜寻专家 更新时间:2023-10-31 00:31:50 25 4
gpt4 key购买 nike

我正在使用在某些情况下运行 __debugbreak() 的第 3 方 C++ DLL,并且在这样做之前没有检查 IsDebuggerPresent()。当这种情况发生在调试器之外(例如,最终用户运行应用程序)时,这会导致我的应用程序“崩溃”。我想捕获它并自己处理它,或者至少忽略它。

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

::SetUnhandledExceptionFilter(OnUnhandledException);

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

    __try
{
__debugbreak();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("caught");
}

try/catch(...) 不起作用。

    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 INT 3),或者至少改变行为?

最佳答案

断点生成EXCEPTION_BREAKPOINT 结构异常。您不能使用 try/catch 来捕获它,因为它不会被转换为 C++ 异常,无论/EHa 开关或 _set_se_translator 是什么。 EXCEPTION_BREAKPOINT 是一个特殊的异常。

首先,您应该知道 catch block 和 __except block 仅在展开堆栈后执行。这意味着在处理程序 block 之后继续执行,而不是在调用 __debugbreak() 之后。因此,如果您只想跳过 EXCEPTION_BREAKPOINT,同时在 int 3 指令之后继续执行。您应该使用 vector 异常处理程序。这是一个例子:

// 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)

关于c++ - 使用 __debugbreak() 尝试/捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33006974/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com