简单的赋值导致错误的值

12
private static void convert(int x) {
    // assume we've passed in x=640.

    final int y = (x + 64 + 127) & (~127);
    // as expected, y = 768

    final int c = y;
    // c is now 320?!
}

以上代码为什么会产生上述值的合理解释?此方法是从JNI中调用的。传递的x最初是C++的int类型,被static_cast转换为jint类型,如下所示:static_cast<jint>(x);

在调试器中,当断点设置在y赋值语句处时,我看到x=640。向前单步执行一行,我看到y=768。再向前单步执行一行,c=320。使用调试器,我可以将变量c=y,并且它会正确地分配为768。

此代码是单线程的,每秒运行多次,并且总是观察到相同的结果。

以下是来自下面评论的更新信息

经过一天的调试后,这个问题现在已经完全消失了。如果它没有在整整一天内可重现的话,我会怀疑宇宙射线的原因。这是我很久以来见过的最奇怪的事情。

我会保留此问题一段时间,以便有人能对可能导致这种情况发生的原因有所了解。


1
调试器可能会向你撒谎。记录值并查看结果。 - Alan Stokes
@user2708138,这段C++代码当前是使用-O0编译的(更准确地说,我们没有传递-O值,而-O0是默认值)。 - Steve Prentice
1
@user2708138,“final”在这里的意思是我不会改变该变量的值,只有初始值。感谢您对解决问题的建议。然而,我可以通过在此方法中进一步使用“y”来执行其他工作来解决这个问题。我在这个问题中特别寻找的是任何合理的解释,说明可能导致这个问题。我个人从未见过像这样的情况,并困惑于为什么会发生这种情况。 - Steve Prentice
1
我已经拿取上面的代码,并添加了System.out.println(c);,将其放入Java类中,编译成一个类文件,创建一个创建JVM(版本1.6)的C ++程序,查找类和方法,然后调用env->CallStaticVoidMethod(class, method, static_cast<jint>(640));,它会产生768。我不知道320来自哪里...如果您在没有JNI的情况下从Java测试程序中执行该函数,它是否有效? - Jerry Jeremiah
1
这一定是来自JNI另一侧的一些阴险腐败 - 但非常奇怪它能够引起这样的影响,并且可以重复。 - Alan Stokes
显示剩余7条评论
3个回答

1

步骤01:正确编译,参见您发布帖子下的评论。

如果需要,我可以用以下代码实现: C# 代码:

private void callConvert(object sender, EventArgs e)
        {
            string myString = Convert.ToString(convert123(640));
            textBox1.Text = myString;
        }
    private static int convert123(int x) {
    // assume we've passed in x=640.
    int y = (x + 64 + 127) & (~127);
    // as expected, y = 768
    int c = y;
    // c is now 320?!
    return (c);
}

但这是一段C#代码

还有一个提示,永远不要使用编译器中已经作为标准使用的名称来调用您的函数。在大多数语言中,convert是被使用的。

(system.convert)

1
这并没有回答所问的问题——我正在寻找一种可能解释所见行为的解释,而不是工作代码。谢谢。 - Steve Prentice

1

最近您设置过c为320吗?如果是的话,它可能已经被存储在某个内存中,编译器可能已经重新分配了它的值,而不是应该的值。但这只是我的猜测。


在这段代码中,c 总是被赋值为 y -- 从不赋给其他任何变量。对于我来说唯一有趣的是 c 是320, 它是 x 的一半,但除此之外我无法找到它们之间的联系。 - Steve Prentice
我感到惊讶,难道编译器有什么问题吗?否则,我不知道发生了什么。非常奇怪。 - exitcode

1

如果程序针对内存使用进行了优化,那么临时变量的内存字节大小可能会成为问题。调试器可能不可靠。我看到如果临时变量 ~127 存储在一个字节中,那么您可能会遇到观察到的情况。这完全取决于运行时存储在 ~127 中的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接