如何处理从 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
做了很多事情,包括内存重新分配和区域填充的创建——在这种情况下都是徒劳的。在这种情况下不应该画一条线吗?
我使用的是矢量图形类型的应用程序。 (有点像 Adobe Illustrator 让你做的事情。)所以你在这里看到的只是用户使用鼠标绘制的任意弧线的快照。 (当那个 API 导致错误时。)所以我真的不明白我还能如何处理那个错误消息,或者我应该做些什么不同的事情(除了编写我自己的 arc 函数,我猜。)
@c00:既然您现在知道一个可能的原因,即为什么调用会返回内存不足错误代码(即遇到数字限制),您可能应该修改您的问题并提取 @987654321 @。听起来像是其他人可能已经遇到或即将遇到但还不知道的问题。很可能是一个比当前分数更有价值的问题。
@IInspectable:好吧,我不是在这里投票的人。另外,正如我上面所说,我无法制作可重复的示例。这是一个零星的问题。在这一点上,我将在 Graphics::DrawArc
和 GraphicsPath::AddArc
似乎表现出这一点的函数上执行此操作:bool bResult = status == Gdiplus::Ok || status == Gdiplus::Status::OutOfMemory
直到有人提出更好的解决方法(除了发布编程陈词滥调。)这似乎工作正常(即绘制弧线)即使函数返回OutOfMemory
。我们可能会将其归咎于 MSFT 无法编写无缺陷的代码......以上是关于如何处理从 Gdiplus::DrawArc 返回的零星 OutOfMemory 错误代码?的主要内容,如果未能解决你的问题,请参考以下文章