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

时间:2016-02-29 11:03:31

标签: c++ debugging visual-c++ timer

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

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

我想完成任务:    - 在调试期间自动释放文件锁以进行编辑。    - 进程恢复后自动重新加载文件    - 防止定时器在调试停止期间触发哪个溢出    - 从计时器中减去调试所花费的时间

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

编辑: 我查看了用于调试器集成的Windows API函数,但似乎ContinueDebugEvent等函数仅适用于调试器的编写器,而且从不用于正在调试的进程。

编辑2: 看起来调试DbgBreakPoint函数可能是一种在调试器想要破坏进程时拦截的方法。

  

附加背后的主要思想是调试器调用   “DebugActiveProcess”函数最终调用了   “RtlCreateUserThread”函数创建一个新的远程线程   目标进程,以“DbgUiRemoteBreakin”函数为新   线程入口点。

(来自http://waleedassar.blogspot.de/2011/12/debuggers-anti-attaching-techniques.html

DbgUiRemoteBreakin似乎调用DbgBreakPoint来实际停止该过程。

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

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

6 个答案:

答案 0 :(得分:1)

免责声明:我自己使用单元测试而不是使用调试器进行深度攻击,但从不说永远不会。

  

是否可以在程序发布时释放资源(文件锁定)   在调试器中停了?

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

  

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

您可以临时编辑代码,以便在计划在调试器中打破它的位置之前和之后执行您希望执行的操作。请不要忘记稍后删除此类临时代码。您还可以通过强制setting the next statement to execute编辑数据内容甚至更改代码的执行顺序,但这样做是很棘手的。

  

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

通过打开OF_SHARE_DENY_NONE标志,还可以选择在调试时不锁定文件。

答案 1 :(得分:0)

这并不漂亮,但假设您没有设置优化标志,请在相关点添加如下内容。

bool executeMe = false;

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

// ... normal code

现在只需在此之前中断,并在评估减速度之后和评估if语句之前,在调试器局部变量视图中将executeMe变量设置为true。

编辑:定时器要求。等。可以通过记录到达断点之前的时间并使用上面的语句在退出调试块后调整计时器来同样满足。

编辑:

WRT自动化,为什么不嵌入在程序中触发断点的条件并在调用__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
}

答案 2 :(得分:0)

我还不能评论,所以对其他答案道歉。

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

BOOL WINAPI IsDebuggerPresent(void);

来自MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms680345%28v=vs.85%29.aspx

根据Jara的回答,我无法找到解决方法。

答案 3 :(得分:0)

你怎么写这样的函数

void break( resource r1)
{
   release resource;
   throw false;
   rebind resource;
}

不是使用普通断点,而是调用break函数,它释放资源,并抛出bool异常。鉴于您的程序没有处理bool异常,您的MSVC调试器将捕获它并为您提供中断选项。然后你可以编辑文件/做所有事情,一旦完成你的恢复,资源就会反弹。

这显然不能让你在运行时使用交互式设置断点,但可能有帮助

答案 4 :(得分:0)

如何使用SetUnhandledExceptionFilter为您检查中断3(调试断点)的进程安装全局处理程序?

处理程序可以释放锁,然后继续EXCEPTION_CONTINUE_SEARCH,基本上将断点中断传递给调试器?

您可以通过查看EXCEPTION_RECORD :: ExceptionCode == EXCEPTION_BREAKPOINT来区分断点

答案 5 :(得分:0)

除了编写自己的调试器或修补visual studio之外,我看到的唯一其他解决方案是扫描所有代码页(标记为执行位)以获取0xCC字节(int 3指令)并通过跳转/调用来修补它们你的函数释放资源然后DebugBreakpoint()。

为了确定0xCC是int3指令还是更长操作码的一部分,您需要反汇编整个应用程序/ dll或者获取所有代码页的副本,以便您可以比较0xCC调试器引入的更改。您可以使用QueueUserAPC()来触发代码页扫描,因为调试器发出信号通知您的线程在放置int3后继续执行,让您有机会在应用程序之前用跳转到我的函数指令替换int3点击int3。

编辑:您不需要复制所有代码页,只需要出现在可执行页面中的所有0xCC字节的地址。