以下结果对我来说没有任何意义。看起来在执行加法或减法之前将负偏移量转换为无符号。
double[] x = new double[1000];
int i = 1; // for the overflow it makes no difference if it is long, int or short
int j = -1;
unsafe
{
fixed (double* px = x)
{
double* opx = px+500; // = 0x33E64B8
//unchecked
//{
double* opx1 = opx+i; // = 0x33E64C0
double* opx2 = opx-i; // = 0x33E64B0
double* opx3 = opx+j; // = 0x33E64B0 if unchecked; throws overflow exception if checked
double* opx4 = opx-j; // = 0x33E64C0 if unchecked; throws overflow exception if checked
//}
}
}
虽然使用负偏移量可能看起来很奇怪,但它有一些用例。在我的例子中,它反射(reflect)了二维数组中的边界条件。
当然,溢出并没有太大的伤害,因为我可以使用未检查的或通过将值的符号取反并将其应用于操作数的模数来将值的符号移动到操作中。
但这种行为似乎没有记录。根据MSDN我不希望负偏移量有问题:
You can add a value n of type int, uint, long, or ulong to a pointer, p,of any type except void*. The result p+n is the pointer resulting from adding n * sizeof(p) to the address of p. Similarly, p-n is the pointer resulting from subtracting n * sizeof(p) from the address of p.
最佳答案
此问题已在 roslyn\RyuJIT 问题跟踪器中以各种形式多次提出。我第一次发现你可以在这里看到:When adding integer to pointer in checked context add.ovf.un instruction is generated
事实上,如果您查看生成的 IL,您会发现 add.ovf.un(“使用溢出检查添加无符号整数”)指令是在已检查的上下文中发出的,而不是在未检查的上下文中发出的。在我们的例子中,此函数的第一个操作数是无符号 native int(一种 UIntPtr),表示 double* 指针。第二个操作数在那个问题(2015 年)和现在是不同的。
在出现该问题时,第二个操作数是 Int32,正如您所期望的那样。但是,使用 UIntPtr 和 Int32 执行 add.ovf.un 在 x86 和 x64 中表现不同。在 x86 中,它抛出溢出异常(对于负数),因为,好吧,第二个操作数是负数。但是,在 x64 中,JIT 会将 Int32 零扩展到 64 位(因为 native 指针现在是 64 位)。它将对其进行零扩展,因为它假定它是无符号的。但是负数 Int32 的零扩展将导致大的 正数 64 位整数。
结果,如果在x64中给指针加上负值Int32,在出现上述问题的时候,并不会抛出溢出异常,而是给指针加上了错误的值,这是当然更糟。
问题以“无法修复”结束:
Thanks for the detailed report here!
Given the narrow scope of the bug though and that the behavior is consistent with the native compiler we are "won't fixing" the bug at this time.
但是,人们对所描述的 x64 行为并不十分满意,因为 x64 可以在没有意识到的情况下默默地生成指向未知位置的指针。经过长时间的辩论,这个问题在 2017 年作为 this issue 的一部分得到了解决。 .
修复是强制将 Int32 转换为 IntPtr,当您将其添加到指针时,在已检查的上下文中。这样做是为了防止在 x64 中自动扩展上述 Int32。
因此,如果您现在查看为您的案例生成的 IL,您将看到在传递给 add.ovf.un 之前,Int32 现在被转换为 IntPtr 与 conv.i IL 指令。这导致在 x86 和 x64 上将负整数添加到已检查上下文中的指针总是抛出溢出异常。
在任何情况下,在检查的上下文中为指针添加发出 add.ovf.un 的原始问题没有解决,而且很可能不会解决,因为它被关闭为“不会fix”,因此您必须意识到这一点,并自行决定如何在您的特定场景中克服这个问题。
关于c# - 指针偏移导致溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49498158/
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame
我正在尝试获得良好的Ruby编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用self.。但是现在我偶然发现了这个:classMyClass上面的代码导致错误privatemethodsanitize_namecalled但是当删除self.并仅使用sanitize_name时,它会起作用。这是为什么? 最佳答案 发生这种情况是因为无法使用显式接收器调用私有(private)方法,并且说self.sanitize_name是显式指定应该接收sanitize_name的对象(self),而不是依赖于隐式接收器(也是
下面的代码工作正常:person={:a=>:A,:b=>:B,:c=>:C}berson={:a=>:A1,:b=>:B1,:c=>:C1}kerson=person.merge(berson)do|key,oldv,newv|ifkey==:aoldvelsifkey==:bnewvelsekeyendendputskerson.inspect但是如果我在“ifblock”中添加return,我会得到一个错误:person={:a=>:A,:b=>:B,:c=>:C}berson={:a=>:A1,:b=>:B1,:c=>:C1}kerson=person.merge(berson
>>a=5=>5>>b=a=>5>>b=4=>4>>a=>5如何将“b”设置为实际的“a”,以便在示例中,变量a也将变为4。谢谢。 最佳答案 classRefdefinitializeval@val=valendattr_accessor:valdefto_s@val.to_sendenda=Ref.new(4)b=aputsa#=>4putsb#=>4a.val=5putsa#=>5putsb#=>5当您执行b=a时,b指向与a相同的对象(它们具有相同的object_id).当你执行a=some_other_thing时,a将指向
我有一个ruby脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用