条件断点在不应该触发时触发

Posted

技术标签:

【中文标题】条件断点在不应该触发时触发【英文标题】:Conditional breakpoint triggers when it should not 【发布时间】:2018-10-29 16:50:51 【问题描述】:

我正在调查由于本机代码中发生的错误而导致 JVM 崩溃的异常。为此,我将 VS 附加到 javaw 进程并调试与我的问题相关的函数。

我目前看的函数如下:

JNIEXPORT void JNICALL Java_org_bytedeco_javacpp_BoolPointer_allocateArray(JNIEnv* env, jobject obj, jlong arg0) 
    bool* rptr = new (std::nothrow) bool[arg0];
    jlong rcapacity = arg0;
    JavaCPP_initPointer(env, obj, rptr, rcapacity, rptr, &JavaCPP_org_bytedeco_javacpp_BoolPointer_deallocateArray);

这是 JNI 生成的代码,用于实现 Java 和本机代码之间的通信。

由于我怀疑某个条件会触发最终导致 JVM 硬崩溃的未处理异常,因此使用断点来调查上面显示的函数。

断点是有条件的,并且满足以下条件:

"arg0 < 1" is "True"

它必须在一个或负值的值上触发。显然我设置不正确,因为断点在arg0 值上反复触发,例如3178311

首先我想到了一个溢出,VS 错误地转换了 Local 窗口中的值,其中变量在调试时显示。但是有低至 8900 的值,这使得这个想法不太可能。

过去我也注意到,有时值不会立即刷新,所以我总是单步执行函数,当断点触发时,值始终大于 0。

我做错了什么?为什么我的断点会触发? VS 是否正确解析arg0

谢谢。

【问题讨论】:

【参考方案1】:

如果您将断点放在代码的第一行,则参数的值尚未在 VS 中初始化(如果您手动进入函数也会发生这种情况)。将断点放在第二行(左大括号之后的任何位置),它可能会起作用。

【讨论】:

谢谢。所以问题在于将中断放在方法签名的行。据我了解,当时 VS 不知道 arg0?无论如何,这有帮助。 @Mär 如果你看反汇编,你会经常发现一些参数是从寄存器压入堆栈的。这发生在左大括号和函数的第一行“之间”。来自编译器的调试信息大概只告诉调试器这些值的堆栈位置(并且调试器在到达第一行之前不知道这是错误的)。调试信息也可以跟踪这一点,但这对于大多数用途来说是无用的,只会让它膨胀。

以上是关于条件断点在不应该触发时触发的主要内容,如果未能解决你的问题,请参考以下文章

实现ABAP条件断点的三种方式

巧用条件断点实现更好的调试

OD调试器断点——条件断点

如何在 Visual C++ 中添加条件断点

VS调试技巧:如何让断点在for循环中变量满足某个条件的时候停下来(条件调试)

VS调试技巧:如何让断点在for循环中变量满足某个条件的时候停下来(条件调试)