问题描述
我正在编写一些可以在字节数组上执行按位布尔运算的例程,并且遇到了我认为C#不安全的错误
码。我正在粘贴下面的控制台应用程序。任何人都可以给出
的解释,或者已经报告过这类问题吗?
谢谢。
使用System;
使用System.Collections.Generic;
使用System.Text;
名称空间UnsafeBug
{
class program
{
static void Main(string [] args)
{
byte [] dest = new byte [] {0x01,0xff};
byte [] sdata1 = new byte [] {0x01,0xff};
UnsafeOr (sdata1,dest,dest,7);
for(int ii = 0; ii< dest.Length; ii ++)
{
Console.WriteLine(" Byte {0} = 0x {1:X2}",ii + 1,dest [ii]);
}
Console.WriteLine(按Enter键退出...); Console.ReadLine();
}
// OR'将'2'字节组合成''dest''而不触及
''dest''的前几位。
//允许源/目的地相同。
static void UnsafeOr(byte [ ] src1,byte [] src2,byte [] dest,int
firstBit)
{
byte mask =(byte)(0x80> ;> firstBit);
int nbytes = Math.Min(Math.Min(src1.Length,src2.Length),
dest.Length);
不安全
固定(字节* s1data =& src1 [0],s2data =& src2 [0],ddata =
& dest [0])
{
byte * s1ptr = s1data;
byte * s2ptr = s2data;
byte * dptr = ddata;
#if false
//此版本有效
byte val =(byte)(* dptr&〜mask);
* dptr ++ =(byte)(val |((* s1ptr ++ | * s2ptr ++)& mask));
#else
//此版本不起作用
* dpt r ++ =(byte)((* dptr& 〜面具)| ((* s1ptr ++ |
* s2ptr ++)& mask));
#endif
for(int ii = 1; ii< nbytes; ii ++)
{
* dptr ++ =(byte)(* s1ptr ++ | * s2ptr ++);
}
}
}
}
}
}
I was writing some routines which could do bitwise boolean operations
on byte arrays, and I ran into what I think is a bug with C#''s unsafe
code. I am pasting a console application below. Can anyone give an
explanation, or has this type of problem been reported already?
Thanks.
using System;
using System.Collections.Generic;
using System.Text;
namespace UnsafeBug
{
class Program
{
static void Main(string[] args)
{
byte[] dest = new byte[] { 0x01, 0xff };
byte[] sdata1 = new byte[] { 0x01, 0xff };
UnsafeOr(sdata1, dest, dest, 7);
for (int ii = 0; ii < dest.Length; ii++)
{
Console.WriteLine("Byte {0} = 0x{1:X2}", ii + 1, dest[ii]);
}
Console.WriteLine("Hit Enter to quit..."); Console.ReadLine();
}
// OR''s together 2 byte arrays into ''dest'' without touching the
first few bits of ''dest''.
// it is allowed for sources/destinations to be the same.
static void UnsafeOr(byte[] src1, byte[] src2, byte[] dest, int
firstBit)
{
byte mask = (byte)(0x80 >> firstBit);
int nbytes = Math.Min(Math.Min(src1.Length, src2.Length),
dest.Length);
unsafe
{
fixed (byte* s1data = &src1[0], s2data = &src2[0], ddata =
&dest[0])
{
byte* s1ptr = s1data;
byte* s2ptr = s2data;
byte* dptr = ddata;
#if false
// this version works
byte val = (byte)(*dptr & ~mask);
*dptr++ = (byte)(val | ((*s1ptr++ | *s2ptr++)&mask));
#else
// this version does not work
*dptr++ = (byte)((*dptr & ~mask) | ((*s1ptr++ |
*s2ptr++)&mask));
#endif
for (int ii = 1; ii < nbytes; ii++)
{
*dptr++ = (byte)(*s1ptr++ | *s2ptr++);
}
}
}
}
}
}
推荐答案
< snip>
我不相信这是一个错误,我不相信它有什么可以用不安全的代码做b $ b。这是一个较小的应用程序,显示相同的效果
没有任何不安全的代码。
使用系统;
class Test
{
static void Main()
{
int [] x = {10} ;
int i = 0;
x [i ++] = i;
Console.WriteLine(x [0]);
}
}
这将打印出1而不是0(这是你所期望的,我
相信)。
您所看到的是在分配右侧的
评估之前执行的后缀增量运营商。
根据规范,这是完全正确的。
-
Jon Skeet - < sk***@pobox.com>
博客:
如果重新请小组,请不要给我发邮件
<snip>
I don''t believe this is a bug, and I don''t believe it has anything to
do with unsafe code. Here''s a smaller app which shows the same effect
without any unsafe code.
using System;
class Test
{
static void Main()
{
int[] x = {10};
int i=0;
x[i++] = i;
Console.WriteLine (x[0]);
}
}
That will print out 1, not 0 (which is what you''d have expected, I
believe).
What you''re seeing is the postfix increment being executed before the
evaluation of the right hand side of the assignment operator.
This is entirely correct according to the specification.
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
问题在于,在右侧之前评估作业的左侧是
。首先,* dptr ++被评估,
递增dptr但仍然产生正确的目的地
地址。当事后评估右侧时,dptr已经增加,因此它指向不同的位置。
所以你可以将你的代码更改为
* dptr =(byte)((byte)(* dptr ++&〜mask)|((* s1ptr ++ | * s2ptr ++)& mask));
或(可能更安全)
* dptr =(byte)((byte)(* dptr&〜mask)|((* s1ptr ++ | * s2ptr ++) & mask));
dptr ++
HTH,
Stefan
The problem lies in the fact that left side of the assignment is
evaluated before the right side. First, *dptr++ is evaluated,
incrementing dptr but still resulting in the correct destination
address. When the right side is evaluated afterwards, the dptr is
already incremented so it points to a different location.
So you can either change your code to
*dptr = (byte)((byte)(*dptr++ & ~mask) | ((*s1ptr++ | *s2ptr++)&mask));
or (maybe safer)
*dptr = (byte)((byte)(*dptr & ~mask) | ((*s1ptr++ | *s2ptr++)&mask));
dptr++
HTH,
Stefan
这篇关于C#不安全的Bug的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!