C# 程序似乎正在修改标记为只读的参数
C# program seems to be modifying a parameter marked as readonly
我有一个名为 ARCMF 的函数,它应该 return 为每个相同的输入集 state
和 keys
都传递相同的伪随机输出使用关键字 in
的只读引用。但是,当我两次尝试 运行 这个函数时,第一个和第二个结果永远不会彼此相等(但每次重新启动程序时都相等)。经过大量调试后,似乎有问题的变量被修改了。我尝试将其设置为只读,但它仍然以某种方式被修改。这让我难住了好几个小时...
All of my code is here on this repo.
This is the variable in question (from now on I will refer to as IV) which I have in a watch window during debugging, and I pass it into a function called 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);
之后
为了帮助展示这一点,这里是一些屏幕截图。
Before ( I cant embed images :( ) and After.
And the function itself looks like this:
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:将 Permutate 函数更改为
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;
}
没有区别。
因为您使用的是 ref
关键字。
它允许 sub-methods 修改内存中的参数值。
在您的情况下,当您每次设置值时,参数 output
(输入 byte-structure )被修改两次:
io[i] = (byte)((io[i] * seed % 256) ^ table[i]);
.
您正在将它与 Ref 关键字混在一起。 Ref 将修改这些值。
制作副本并使用副本。
var output = new byte[state.Length];
state.CopyTo(output, 0);
or
var output = state.ToArray();
我有一个名为 ARCMF 的函数,它应该 return 为每个相同的输入集 state
和 keys
都传递相同的伪随机输出使用关键字 in
的只读引用。但是,当我两次尝试 运行 这个函数时,第一个和第二个结果永远不会彼此相等(但每次重新启动程序时都相等)。经过大量调试后,似乎有问题的变量被修改了。我尝试将其设置为只读,但它仍然以某种方式被修改。这让我难住了好几个小时...
All of my code is here on this repo.
This is the variable in question (from now on I will refer to as IV) which I have in a watch window during debugging, and I pass it into a function called 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);
为了帮助展示这一点,这里是一些屏幕截图。
Before ( I cant embed images :( ) and After.
And the function itself looks like this:
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:将 Permutate 函数更改为
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;
}
没有区别。
因为您使用的是 ref
关键字。
它允许 sub-methods 修改内存中的参数值。
在您的情况下,当您每次设置值时,参数 output
(输入 byte-structure )被修改两次:
io[i] = (byte)((io[i] * seed % 256) ^ table[i]);
.
您正在将它与 Ref 关键字混在一起。 Ref 将修改这些值。
制作副本并使用副本。
var output = new byte[state.Length];
state.CopyTo(output, 0);
or
var output = state.ToArray();