在不安全代码块之后丢失的变量

本文关键字:变量 之后 不安全 代码 | 更新日期: 2023-09-27 18:02:02

我有一个很奇怪的问题。下面是我的代码:

<declare E,JV>
<perform some actions with E>
JV.Math_Mul(E);

////

public new void Math_Mul(Matrix a)
    {
        double[,] vC = new double[a.ColCount, this.RowCount];

        externExtensions.MatMul(vC,a.Values ,this.Values, a.RowCount, this.ColCount, a.ColCount);
        Values = vC;
        CopyB(B.Values,vC);
     }
    static unsafe void CopyB(double[,] B, double[,] val)
    {
        int Col = val.GetLength(1);
        int j = 0;
        fixed (double* pA = B, pB = val)
        {
            for (int i = 0; i < val.Length; i++)
            {
                if (i != j * Col)
                    pA[i-j] = pB[i];
                else
                    j++;
            }
        }
    }

执行CopyB函数后,E发生了一些事情(这是非常奇怪的,因为它不是CopyB的参数)和VS 2012告诉我:无法获得本地或参数'E'的值,因为它在这个指令指针上不可用,可能是因为它已经被优化了。代码优化是关闭的,这段代码工作得很好,直到我做了CopyB。那么,问题是什么呢?E发生了什么,我该怎么做?

PS CopyB是为了在乘法后更快地解析矩阵而实现的,这是我的数学工具的一部分,我使用块矩阵。

我将非常感谢任何帮助!

在不安全代码块之后丢失的变量

让我们简化你的问题:

我正在调试器中查看此代码。

static void Foo(int a, int b)
{
  DoSomething(a);
  DoSomethingElse(b);
}

有时在DoSomething运行后试图在调试器中查看a时,我得到消息"无法获得本地或参数'a'的值,因为它在此指令指针上不可用,可能是因为它已被优化了。"这是什么意思?

形式参数是变量,这意味着它必须被实现为存储位置。由于形式参数的生命周期很短,因此可以在短期池上分配该存储位置。这意味着抖动将使其成为堆栈位置寄存器

假设它是一个寄存器。寄存器是x86领域的稀缺资源,因此抖动可能想要在DoSomethingElse中使用该寄存器。它知道这样做是安全的,因为它知道DoSomethingElse之后没有任何东西指向a;就抖动而言,a现在是"死亡"的,所以它的寄存器可以用于其他东西。

调试器知道寄存器不再意味着a,所以它不会让你被愚弄,认为寄存器的值是a的值。这个值没有了,因为它的存储空间现在被其他东西占用了。

所以这解释了为什么当我添加一个新方法调用时调试器的行为发生了变化?

是的。在原始程序中,抖动不需要重用寄存器,因此在整个方法调用过程中它都具有其原始值。

您的实际场景只是这个场景的一个更复杂的版本,其中包含三个方法。抖动可能是为了其他目的而重新使用代表变量E的寄存器。