C++ 调试中断期间释放资源(C+;+;,MSVC)

C++ 调试中断期间释放资源(C+;+;,MSVC),c++,debugging,visual-c++,timer,C++,Debugging,Visual C++,Timer,当程序在调试器中停止时,是否可以释放资源(文件锁、计时器) 更一般地说,我能在MSVC停止程序调试之前和恢复执行之后执行代码吗 我想实现以下目标: -在调试期间自动释放文件锁以进行编辑。 -进程恢复后自动重新加载文件 -防止计时器在调试停止期间触发溢出 -从计时器中减去调试所花费的持续时间 解决方法:如果我无法在调试器停止程序之前执行代码,那么在程序中以编程方式检测调试器停止了应用程序将有很大帮助 编辑: 我研究了用于调试器集成的Windows API函数,但是像ContinueDebugEv

当程序在调试器中停止时,是否可以释放资源(文件锁、计时器)

更一般地说,我能在MSVC停止程序调试之前和恢复执行之后执行代码吗

我想实现以下目标: -在调试期间自动释放文件锁以进行编辑。 -进程恢复后自动重新加载文件 -防止计时器在调试停止期间触发溢出 -从计时器中减去调试所花费的持续时间

解决方法:如果我无法在调试器停止程序之前执行代码,那么在程序中以编程方式检测调试器停止了应用程序将有很大帮助


编辑: 我研究了用于调试器集成的Windows API函数,但是像
ContinueDebugEvent
这样的函数似乎只适用于调试器的编写者,而不适用于正在调试的进程


编辑2: 当调试器想要中断进程时,对DbgBreakPoint函数进行热修补似乎是一种拦截的方法

附加的主要思想是调试器调用 “DebugActiveProcess”函数,该函数以调用 “RtlCreateUserThread”函数创建一个新的远程线程到 目标进程,将“DbgUiRemoteBreakin”函数作为新的 线程入口点

(来自)

DbgUiRemoteBreakin似乎调用DbgBreakPoint来实际停止进程


编辑3: 我对DbgBreakPoint和DebugBreak进行了热修补,以查看在以交互方式中断时是否从MSVC调试器调用了这些方法。唉,他们没有!MSVC调试器似乎只是在断点位置插入
int 3
,而不调用任何进程方法


编辑4:
读取结构化异常及其与DebugBreak陷阱的交互也会导致死区:当遇到断点时,中断3将首先到达内核,内核将首先将结构化异常传递给调试器(如果已连接)。调试器处理中断,而应用程序从未看到它。

免责声明:我自己使用单元测试,而不是对调试器进行如此深入的黑客攻击,但从不说“永不”

程序运行时是否可以释放资源(文件锁) 在调试器中停止

调试器不包含此类功能。最简单的方法是使用或其他类似的工具。但是,如果您继续 此后,程序不再释放资源,后续访问这些资源的尝试将失败

更一般地说,我能在MSVC停止程序之前执行代码吗 用于调试和恢复执行后

您可以临时编辑代码,以便在您计划在调试器中中断代码的位置之前和之后执行您希望它执行的任何操作。只是别忘了以后删除这些临时代码。您还可以通过强制方式编辑数据内容,甚至更改代码的执行顺序,但这很难正确执行

我的程序锁定一个文件,我想在调试期间交换该文件


另外,在调试时,还可以选择不锁定文件,方法是使用flag打开。

这不太好,但假设没有设置优化标志,请在相关点添加如下内容

bool executeMe = false;

if(executeMe) {
    // Code to release lock / close file ...
}

// ... normal code
现在只需在此之前中断,并在计算减速后和计算if语句之前,在debugger local variables视图中将executeMe变量设置为true

编辑:定时器要求等。同样,在到达断点之前记录时间,并在退出调试块后使用如上所述的语句将计时器调整回原位,可以满足这一要求

编辑:

WRT automation,为什么不在程序中嵌入触发断点的条件,并在调用_debugbreak()之前进行设置?您使用的条件可能是程序内部的条件,或者类似于触发器文件的存在,如下所示

bool debugging = false;

struct stat unused;
if(!stat('.\\.debugflag',&unused)) {
    // Release locks, Close files, Stop timers .etc.
    // ...
    // Hook debuger. At this point you should be right to debug
    debugging = true;
    __debugbreak();  
}

// Code to debug ....

if(debugging) {
    // Cleanup after debug
}

我还不能发表评论,所以对其他答案表示歉意

在MS Visual Studio中,您可以使用API调用检测应用程序是否在调试器下运行

BOOL WINAPI IsDebuggerPresent(void);
从MSDN:


我看不出有什么办法可以按照Jara的答案编写自己的锁定。

编写这样的函数怎么样

void break( resource r1)
{
   release resource;
   throw false;
   rebind resource;
}
不使用普通断点,而是调用break函数,该函数释放资源并引发bool异常。假设您的程序不处理bool异常,那么您的MSVC调试器将捕获它并提供中断选项。然后你可以编辑文件/做任何事情,一旦你完成了,点击resume,资源就会恢复


这显然不允许您在运行时交互式设置断点,但可能会有帮助,使用SetUnhandledExceptionFilter为您的进程安装全局处理程序,在其中检查中断3(调试断点)如何

处理程序可以释放锁,然后继续执行异常\u continue\u搜索,本质上是将断点中断传递给调试器


您可以通过查看EXCEPTION_RECORD::ExceptionCode==EXCEPTION_breakpoint来区分断点。除了编写自己的调试器或修补visual studio之外,我看到的唯一其他解决方案是扫描所有代码页(用执行位标记)以查找0xCC字节(int 3指令)并通过对释放资源的函数的跳转/调用对它们进行修补,然后调用DebugBreakpoint()

为了确定0xCC是int3指令还是较长操作码的一部分,您需要反汇编整个应用程序/dll或复制所有代码页,以便比较调试器引入的0xCC更改。您可能可以使用QueueUserAPC()触发代码页扫描,因为调试器在放置int3后向您的线程发出恢复执行的信号,从而使您有机会重新执行