【问题标题】:Flood fill algorithm memory leak洪水填充算法内存泄漏
【发布时间】:2023-03-27 22:43:01
【问题描述】:

我在某处发生了内存泄漏。我已经搜索了很多次,对我来说它看起来很可靠。我只是……找不到…… 好的,背景。这是一个堆栈驱动的洪水填充,这段代码是我向堆栈添加东西的唯一地方。代码比较多,如果没有人发现内存泄漏,我再贴一些。

这是最奇怪的部分。该代码仅适用于一种颜色+线条艺术(图片纹理),但是当使用多种颜色并使用填充桶时,我会遇到那些奇怪的内存泄漏。

 //descend to the floor
            while(true)
            {

                if(++iterator > total)
                {
                    Debug.Log("broke in the stupid down loop...");
                    break;
                }

                //if we hit line art or a color we're not changing, break out of the loop
                if(PicTexture.GetPixel((int)coords.x, (int)coords.y).a > .5f ||
                   MyTexture.GetPixel((int)coords.x, (int)coords.y) != ColorToChange || coords.y < 0)
                {
                    break;
                }


                //if we're looking right and find an open spot in our texture
                if(reach.right && MyTexture.GetPixel((int)coords.x + 1, (int)coords.y) == ColorToChange
                   && PicTexture.GetPixel((int)coords.x + 1, (int)coords.y).a < .5f)
                {
                    reach.right = false;    //search it and stop looking right
                    if(!search.Contains(new Vector2((int)coords.x + 1, (int)coords.y)))
                        search.Push(new Vector2((int)coords.x + 1, (int)coords.y));
                }
                else
                {
                    if(MyTexture.GetPixel((int)coords.x + 1, (int)coords.y) != ColorToChange
                       || PicTexture.GetPixel((int)coords.x + 1, (int)coords.y).a >= .5f)   //if theres a wall and we're not looking right
                        reach.right = true; //look for an opening to the rightq
                }

                //same thing for left
                if(reach.left && MyTexture.GetPixel((int)coords.x - 1, (int)coords.y) == ColorToChange
                   && PicTexture.GetPixel((int)coords.x - 1, (int)coords.y).a < .5f)
                {
                    reach.left = false;
                    if(!search.Contains(new Vector2((int)coords.x - 1, (int)coords.y)))
                        search.Push(new Vector2((int)coords.x - 1, (int)coords.y));
                }
                else
                {
                    if(MyTexture.GetPixel((int)coords.x - 1, (int)coords.y) != ColorToChange
                       || PicTexture.GetPixel((int)coords.x - 1, (int)coords.y).a >= .5f)
                        reach.left = true;
                }

                MyTexture.SetPixel((int)coords.x, (int)coords.y, BrushColor);
                coords.y--;
            }   

编辑:我刚刚意识到我忘了提到最奇怪的部分。这段代码工作得很好,直到我使用起始颜色(蓝色)以外的颜色。一旦我改变颜色,即使它变回蓝色,它仍然会破裂。

【问题讨论】:

  • 你怎么知道你有内存泄漏?你有什么症状?您使用了哪些调试工具来尝试识别泄漏源?他们展示了什么?
  • 我一直在使用 Unity 的 Debug.Log() 来抛出调试语句,以查看搜索堆栈有多大,并且如果它卡住了,该迭代器可以让我脱离循环。当我只使用一种颜色时,堆栈大小永远不会超过 75,并且迭代器保持合理的计数。为了不让程序崩溃,我一直在 600,000 次迭代和 100 的堆栈大小时打破循环。
  • 我不认为这是内存泄漏,而是您的算法有问题
  • 不,算法很好,但我接收颜色的方式存在问题。编写颜色选择器代码的人使用的颜色格式与我不同,因此它会遇到不太确定如何处理的颜色,并且基本上只是不断地将搜索添加到堆栈中。

标签: c# memory-leaks unity3d paint flood-fill


【解决方案1】:

首先,使用分析器。我与RedGate's ANTS Memory Profiler 有过愉快的经历。当问题不明显时,这确实是获取所需信息的最快方法。

至于您的代码,我乍一看只注意到您可能在很短的时间内创建了大量的Vector2 对象。我不知道这是否真的导致了您看到的问题。

顺便说一句,GDI+ 像狗一样慢。如果您开始注意到性能不佳,您可能需要考虑使用Bitmap.LockBits 来获取指向内存中图像数据的指针并对其进行操作。以我的经验,GDI+ 根本不适合对尺寸不大的图像进行操作。

【讨论】:

  • 我的狗很快,但我主要使用 GDI+ 来处理矢量图形,而不是位图。为 RedGate +1。
  • 谢谢,虽然我使用的是 Unity 的 texture2d,但它们没有内置的原生 Bitmap.LockBits 函数。这是奇怪的事情。当我启动它时,这段代码工作得很好。直到我改变颜色并尝试使用泛光填充,它才开始出现异常。不过颜色应该无关紧要,因为它只是在寻找替换颜色。
【解决方案2】:

我想通了。事实证明,这并不完全是我的错。编写颜色选择器代码的人使用的颜色格式与我不同,但我们使用的引擎有时会将一种格式隐式转换为另一种格式,这就是它有时仍然有效的原因。非常非常奇怪。 感谢你们的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    相关资源
    最近更新 更多