如何处理从 Gdiplus::DrawArc 返回的零星 OutOfMemory 错误代码?

Posted

技术标签:

【中文标题】如何处理从 Gdiplus::DrawArc 返回的零星 OutOfMemory 错误代码?【英文标题】:How to handle sporadic OutOfMemory error codes returned from Gdiplus::DrawArc? 【发布时间】:2019-08-26 07:14:44 【问题描述】:

据我所知,Gdiplus::DrawArc 是唯一能做到这一点的 GDI+ 函数。

我在绘制弧线的生产代码中发现了从该函数返回的零星错误,因此遇到了这个错误。然后我添加了一些调试代码来测试并确定我的断点命中:

我在这个伪代码中添加了相同的值,它是我实际代码的一个小副本:

    HDC hDC = ::GetDC(hDlg);
    Gdiplus::Graphics grx(hDC);
    Gdiplus::Pen pen(Gdiplus::Color(1, 2, 3));

    Gdiplus::Status status;
    status = grx.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
    ASSERT(status == Gdiplus::Status::Ok);
    status = grx.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
    ASSERT(status == Gdiplus::Status::Ok);

    Gdiplus::Status stat = grx.DrawArc(&pen, 81, 27, 82 - 81, 242 - 27, (float)-49.573921259900864, (float)1.1629763045451398);
    if(stat != Gdiplus::Ok)
    
        ASSERT(NULL);
    

    ::ReleaseDC(hDlg, hDC);

而且效果很好。然后我将它添加到一个循环 100000 次的循环中,它也运行良好。

我仍然从那个Gdiplus::DrawArc返回零星的Gdiplus::Status::OutOfMemory

有谁知道,我该怎么处理?

【问题讨论】:

【参考方案1】:

您必须弄清楚Gdiplus 中发生了什么。 Gdiplus::Status::OutOfMemory 并不总是内存不足状态的结果,而是由某些资源生成过程在链中返回InvalidPointer 的结果。这可能是由给定的语义疯狂或超出范围的参数引起的。例如。在LinearGradientBrush 内创建画笔可能会失败,因为在某些时候InferAffineMatrix(int this, GpPointF *points, GpRectF *rect) 发现矩形区域小于“epsilon”值:

 rectArea = bottom * right - x * y - (y * width + x * height);
 rectArea = fabs(rectArea);
 if ( rectArea < 0.00000011920929 )
    return InvalidParameter;

在你的情况下,你可能应该追查原因,但通常是这样的。

MS 在忽略某些返回状态并返回其他状态方面做了一些糟糕的选择,这导致了一些愚蠢的错误消息。通常唯一的解决方法是解决该问题,并且不对太小或格式错误的对象进行填充、渲染或变换。

【讨论】:

谢谢。我喜欢这个"Gdiplus::Status::OutOfMemory isn't always a result of out-of-memory state" ... 一定喜欢 MSFT :) 所以你说的是我应该忽略它。我读对了吗? @c00000fd 在某些情况下忽略可能会导致更严重的问题。我认为,在您的情况下,实际上是因为您的弧线实际上是一条直线-边界矩形是一个像素宽?正确的方法是解决它.. 如果你检查公共代码,你会发现DrawArc 做了很多事情,包括内存重新分配和区域填充的创建——在这种情况下都是徒劳的。在这种情况下不应该画一条线吗? 我使用的是矢量图形类型的应用程序。 (有点像 Adob​​e Illustrator 让你做的事情。)所以你在这里看到的只是用户使用鼠标绘制的任意弧线的快照。 (当那个 API 导致错误时。)所以我真的不明白我还能如何处理那个错误消息,或者我应该做些什么不同的事情(除了编写我自己的 arc 函数,我猜。) @c00:既然您现在知道一个可能的原因,即为什么调用会返回内存不足错误代码(即遇到数字限制),您可能应该修改您的问题并提取 @987654321 @。听起来像是其他人可能已经遇到或即将遇到但还不知道的问题。很可能是一个比当前分数更有价值的问题。 @IInspectable:好吧,我不是在这里投票的人。另外,正如我上面所说,我无法制作可重复的示例。这是一个零星的问题。在这一点上,我将在 Graphics::DrawArcGraphicsPath::AddArc 似乎表现出这一点的函数上执行此操作:bool bResult = status == Gdiplus::Ok || status == Gdiplus::Status::OutOfMemory 直到有人提出更好的解决方法(除了发布编程陈词滥调。)这似乎工作正常(即绘制弧线)即使函数返回OutOfMemory。我们可能会将其归咎于 MSFT 无法编写无缺陷的代码......

以上是关于如何处理从 Gdiplus::DrawArc 返回的零星 OutOfMemory 错误代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理从 Undertow 工作线程抛出的异常?

Android:如何处理从右到左的滑动手势

如何处理从 servlet 中的 Angular 应用程序发送的预检请求?

如何处理从我的 GUI 应用程序启动的控制台窗口?

如何处理从 ng-repeat 生成的列表单击并加载下一页

如果列数不同,如何处理从源 spark df 到 hive 表的插入