C#不安全的Bug [英] C# Unsafe Bug

查看:69
本文介绍了C#不安全的Bug的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一些可以在字节数组上执行按位布尔运算的例程,并且遇到了我认为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++);
}
}
}
}
}
}

推荐答案

JS< st ******** @ ic.net>写道:
JS <st********@ic.net> wrote:
我正在编写一些可以在字节数组上执行按位布尔操作的例程,我遇到了我认为是C#的不安全代码的错误。我正在粘贴下面的控制台应用程序。任何人都可以提供
解释,或者已经报告过这类问题吗?
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?




< 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>
http://www.pobox。 com / ~siget 博客: http://www.msmvps.com/ jon.skeet

如果重新请小组,请不要给我发邮件



<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


JS写道:
我正在编写一些可以执行按位布尔操作的例程
在字节数组上,我遇到了我认为是C#的不安全代码的错误。我正在粘贴下面的控制台应用程序。任何人都可以给出一个
解释,或者已经报告过这类问题了吗?
谢谢。

使用System;
使用System.Collections.Generic;
使用System.Text;

命名空间UnsafeBug
{
类程序
{
静态无效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)
{/>字节掩码=(字节)(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
//此版本不起作用
* dptr ++ =(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++);
}
}
}
}
}
}




问题在于,在右侧之前评估作业的左侧是

。首先,* 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


好吧,我想。据我所知,postfix是在

语句执行后完成的。我想我应该看一下

规格的语言。


感谢您的快速回复。

OK, I guess. It was my understanding that postfix was done after the
statement was executed. I suppose I should look at the language
specifications.

Thanks for the quick responses.


这篇关于C#不安全的Bug的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆