使用Graphics.DrawArc可重现的崩溃 [英] Reproducible crash using Graphics.DrawArc

查看:92
本文介绍了使用Graphics.DrawArc可重现的崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的软件绘制技术图纸.一张特定的图纸每次都使用 OutOfMemoryException 使应用程序崩溃.经调查,似乎没有异常.该应用程序不需要大量的内存,也没有使用大量的句柄.我尝试捕获异常,应用程序完成了绘图,没有抛出另一个.实际上,总是只有一个 OutOfMemoryException ,并且始终是导致它的同一图形基元.

Our software renders technical drawings. One particular drawing made the application crash every time with an OutOfMemoryException. Upon investigation, nothing seemed out of the ordinary; the app didn't request a lot of memory, didn't use a lot of handles. I tried catching the exception and the app finished the drawing without throwing another one. In fact, there was always only the one OutOfMemoryException, and it was always the same graphics primitive that caused it.

以下代码是导致此特定崩溃的最低要求.图像大小,笔样式和坐标的确切组合似乎导致了异常.将坐标四舍五入到小数点后三位会使它消失,使图形尺寸变小或使用不带虚线的笔也是如此.

The following code is the minimum required to cause this particular crash. It seems that the exact combination of image size, pen style and coordinates causes the exception. Rounding the coordinates down to three decimals makes it disappear, as does making the graphics dimensions smaller or using a pen without dashing.

using (Bitmap b = new Bitmap(200, 200))
{
  using (Graphics g = Graphics.FromImage(b))
  {
    using (Pen p = new Pen(Color.Black))
    {
      p.DashPattern = new float[]{10.0f, 2.0f};

      RectangleF r = new RectangleF(
        BitConverter.ToSingle(new byte[]{0xD3, 0x56, 0xB3, 0x42}, 0),
        BitConverter.ToSingle(new byte[]{0x87, 0x2D, 0x17, 0x43}, 0),
        BitConverter.ToSingle(new byte[]{0xE2, 0x81, 0xD1, 0x3F}, 0),
        BitConverter.ToSingle(new byte[]{0xE2, 0x81, 0xD1, 0x3F}, 0));
      float st = BitConverter.ToSingle(new byte[]{0x6B, 0xF6, 0x1A, 0x42}, 0);
      float sw = BitConverter.ToSingle(new byte[]{0x6D, 0x33, 0x4F, 0x40}, 0);

      g.DrawArc(p, r, st, sw);
    }
  }
}

在这种情况下,创建变通办法并不复杂,但是我想知道是否有人对此进行了解释.

In this case it's not complicated to create a workaround, but I was wondering if someone had an explanation for this.

推荐答案

System.Drawing是GDI +的包装,GDI +是一个非托管库,它在.NET发行之前已经有很多年了.它遭受C api的典型问题,错误报告相当差. GDI +只有20个不同的错误代码,对于这么大的代码块来说却不多.它们也是非常不透明的,特定的问题是Status :: GenericError.对于许多可能没有共同之处的可能的错误情况,返回的是非常常见的错误.

System.Drawing is a wrapper for GDI+, an unmanaged library that pre-dated the release of .NET by many years. It suffers from a typical problem with a C api, error reporting is rather poor. GDI+ has only 20 distinct error codes, not much for such a large chunk of code. They are also very opaque, a particular doozy is Status::GenericError. A pretty common error that's returned for many possible error conditions that have nothing in common.

System.Drawing不能使这些错误代码更具描述性,因为它们不是设计时描述的. Status :: OutOfMemory也适合该模式.它几乎不能做到这一点,但会生成表示同一件事的托管异常.遗憾的是,这也不是一个好选择,因为OutOfMemoryException在.NET中是如此具体.

System.Drawing could do very little to make these error codes more descriptive, given that they were not descriptive by design. Status::OutOfMemory fits that pattern as well. Very little it could do with that but generate a managed exception that means the same thing. Sadly that wasn't a great choice either since OutOfMemoryException is so very specific in .NET.

这里有很多损失,很少有赢家的方法.您只需要从表面上评估GDI +的错误报告,然后解决问题即可.在这种情况下,避免在极小的弧上使用虚线笔很有可能会解决您的问题.无论如何您都看不到破折号图案.

Lots of lossage here with few ways to win. You just need to take the poor error reporting of GDI+ at face value and patch around the problem. With a high likelihood in this case that avoiding using a dashed pen for very small arcs will solve your problem. You can't see the dash pattern anyway.

这篇关于使用Graphics.DrawArc可重现的崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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