提问人:Nathaniel Aquino 提问时间:2/5/2022 最后编辑:Nathaniel Aquino 更新时间:2/5/2022 访问量:113
C# 程序似乎正在修改标记为只读的参数
C# program seems to be modifying a parameter marked as readonly
问:
我有一个名为 ARCMF 的函数,它应该为每组相同的输入返回相同的伪随机输出,并且它们都通过使用关键字通过只读引用传递。但是,当我尝试运行此函数两次时,第一个和第二个结果永远不会相等(但每次重新启动程序时都是相等的)。经过广泛的调试,似乎有问题的变量被修改了。我尝试将其设置为只读,但它仍然以某种方式被修改。这让我难住了好几个小时......state
keys
in
这是有问题的变量(从现在开始,我将称为 IV),我在调试期间将其放在监视窗口中,并将其传递到一个名为 ARCMF 的函数中......
var arc = new ARC128(key, iv);
var mf0 = arc.ARCMF(iv, arc.Schedule(key, iv, 1));
arc.PrintArray(mf0, "Main Function Iteration 0 Results");
var mf1 = arc.ARCMF(iv, arc.Schedule(key, iv, 1));
arc.PrintArray(mf1, "Main Function Iteration 1 Results");
c.WriteLine(Enumerable.SequenceEqual(mf0, mf1) ? "MF Gen success." : "MF Gen fail.");
internal byte[] ARCMF(in byte[] state, in byte[][] keys)
{
var output = state;
for (int i = 0; i < 9; i++)
{
ARCLT.Permutate(ref output, ARCLT.MBLTv1, i);
ARCBMGR(ref output);
ARCLT.Permutate(ref output, ARCLT.SBLTv1, i);
output = OTPArray(output, keys[i]);
}
return output;
}
IV 的修改专门发生在ARCLT.Permutate(ref output, ARCLT.MBLTv1, i);
为了帮助展示这一点,这里有一些屏幕截图。
internal static void Permutate(ref byte[] io, in byte[] table, int seed = 1)
{
seed = (seed == 0) ? 1 : seed;
for (int i = 0; i <= io.Length - 1; i++)
io[i] = (byte)((io[i] * seed % 256) ^ table[i]);
}
对于那些好奇的人,以下是该程序输出的内容:
Main Function Iteration 0 Results: 785B62AFE54AB7FA7A4EE63D67A311A8
Main Function Iteration 1 Results: F47B4EF85524B92B6F210F9EDCD5786
MF Gen fail.
我该怎么办?
更新 1:将 Permutationate 函数更改为
internal static byte[] Permutate(byte[] io, in byte[] table, int seed = 1)
{
var o = io;
seed = (seed == 0) ? 1 : seed;
for (int i = 0; i <= io.Length - 1; i++)
o[i] = (byte)((o[i] * seed % 256) ^ table[i]);
return o;
}
没有区别。
答:
1赞
Rivo R.
2/5/2022
#1
因为你正在使用关键字。
它允许子方法修改参数在内存中的值。
在本例中,每次使用以下命令设置值时,参数(字节结构类型化)都会被修改两次:ref
output
io[i] = (byte)((io[i] * seed % 256) ^ table[i]);
.
评论
0赞
Nathaniel Aquino
2/5/2022
更改函数无济于事。internal static byte[] Permutate(byte[] io, in byte[] table, int seed = 1) { var o = io; seed = (seed == 0) ? 1 : seed; for (int i = 0; i <= io.Length - 1; i++) o[i] = (byte)((o[i] * seed % 256) ^ table[i]); return o; }
0赞
Train
2/5/2022
#2
你把它和 Ref 关键字混合在一起。Ref 将修改这些值。
复制它并使用该副本。
var output = new byte[state.Length];
state.CopyTo(output, 0);
or
var output = state.ToArray();
评论
0赞
Nathaniel Aquino
2/5/2022
谢谢!这奏效了,尽管我有点困惑为什么......是因为设置在引用上复制吗?output
state
1赞
Amit
2/5/2022
这是因为 new 它在内存堆中创建了一个由变量 “output” 重新保护的新对象,并且对这个新对象进行了任何更改,变量 “state” 引用的旧对象保持不变。您之前的代码未按预期工作,因为调用函数中的变量和“Permutate”函数仍在内存中引用同一对象。推荐阅读 jonskeet.uk/csharp/references.html 和其中的链接
0赞
Nathaniel Aquino
2/5/2022
威尔科,这是有道理的。请务必阅读那篇文章。
评论
readonly
void X(in byte[] v){v[0]=42;}