64位指针运算在C#中,检查运算溢出改变行为 [英] 64-bit pointer arithmetic in C#, Check for arithmetic overflow changes behavior

查看:193
本文介绍了64位指针运算在C#中,检查运算溢出改变行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些不安全的C#code,做指针运算,大块内存上键入字节* ,在64位机器上运行。它正常工作的大部分时间,但是当事情变得很大,我经常得到一些腐败现象在指针变得不正确。

I have some unsafe C# code that does pointer arithmetic on large blocks of memory on type byte*, running on a 64-bit machine. It works correctly most of the time but when things get large I often get some kind of corruption where the pointer gets incorrect.

但奇怪的是,如果我打开检查算术溢/下溢一切正常。我没有得到任何溢出异常。但由于大型演出打我需要没有这个选项运行code。

The strange thing is that if I turn on "Check for arithmetic overflow/underflow" everything works correctly. I do not get any overflow exceptions. But due to the large performance hit I need to run the code without this option.

什么引起这种行为差异?

What could be causing this difference in behavior?

推荐答案

这是一个C#编译器错误(<一href="https://connect.microsoft.com/VisualStudio/feedback/details/675205/c-compiler-performs-sign-extension-during-unsigned-pointer-arithmetic"相对=nofollow>提交的连接)。 <一href="http://stackoverflow.com/questions/6321650/64-bit-pointer-arithmetic-in-c-check-for-arithmetic-overflow-changes-behavior/6334135#6334135">@Grant显示由C#编译器跨$ P $点的 UINT 操作产生的MSIL的签名。这是不对的,根据C#的规范,这里的相关章节(18.5.6):

It's a C# compiler bug (filed on Connect). @Grant has shown that the MSIL generated by the C# compiler interprets the uint operand as signed. That's wrong according to the C# spec, here's the relevant section (18.5.6):

18.5.6指针运算

在不安全的情况下, + - 运营商(§7.8.4和§7.8.5)可以应用于所有指针类型的值,除了无效* 。因此,对于每一个指针类型 T * ,以下运算符隐式定义的:

In an unsafe context, the + and - operators (§7.8.4 and §7.8.5) can be applied to values of all pointer types except void*. Thus, for every pointer type T*, the following operators are implicitly defined:

T* operator +(T* x, int y);
T* operator +(T* x, uint y);
T* operator +(T* x, long y);
T* operator +(T* x, ulong y);
T* operator +(int x, T* y);
T* operator +(uint x, T* y);
T* operator +(long x, T* y);
T* operator +(ulong x, T* y);
T* operator –(T* x, int y);
T* operator –(T* x, uint y);
T* operator –(T* x, long y);
T* operator –(T* x, ulong y);
long operator –(T* x, T* y);

     

由于指针类型 T * 和前pression的前pression P N 类型 INT UINT ULONG ,前pressions 点+ N N + P 计算式的指针值 T * ,从增加的结果 N * sizeof的(T)给出的地址P 。同样,前pression p - N 计算式的指针值 T * ,从减去结果 N * sizeof的(T)点给出的地址

Given an expression P of a pointer type T* and an expression N of type int, uint, long, or ulong, the expressions P + N and N + P compute the pointer value of type T* that results from adding N * sizeof(T) to the address given by P. Likewise, the expression P - N computes the pointer value of type T* that results from subtracting N * sizeof(T) from the address given by P.

由于两位前pressions, P 问:,指针类型的 T * ,前pression 对 - Q 计算由 P 问:,然后把这种差异由的sizeof(T)。结果的类型总是。实际上,对 - Q 计算为((长)(P) - (长)(Q))/的sizeof(T)

Given two expressions, P and Q, of a pointer type T*, the expression P – Q computes the difference between the addresses given by P and Q and then divides that difference by sizeof(T). The type of the result is always long. In effect, P - Q is computed as ((long)(P) - (long)(Q)) / sizeof(T).

如果一个指针运算溢出指针类型的域,结果被截断实现定义的方式,但没有异常产生。

If a pointer arithmetic operation overflows the domain of the pointer type, the result is truncated in an implementation-defined fashion, but no exceptions are produced.

你自己也可以添加一个 UINT 来一个指针,没有隐式转换发生。且操作不溢出的指针类型的域。因此,截断是不允许的。


You're allowed to add a uint to a pointer, no implicit conversion takes place. And the operation does not overflow the domain of the pointer type. So truncation is not allowed.

这篇关于64位指针运算在C#中,检查运算溢出改变行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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