【问题标题】:StackOverFlowException - but oviously NO recursion/endless loopStackOverFlowException - 但显然没有递归/无限循环
【发布时间】:2011-01-08 03:00:27
【问题描述】:

我现在整天都被这个问题所困扰,阅读了数千个谷歌结果,但似乎没有任何反映我的问题甚至接近它......我希望你们中的任何人都朝着正确的方向前进我。

我写了一个客户端-服务器-应用程序(更像是 2 个应用程序) - 客户端收集有关他的系统的数据以及屏幕截图,将所有这些序列化为 XML 流(图片为 byte[]-array ]) 并定期将其发送到服务器。 服务器接收流(通过 tcp),将 xml 反序列化为信息对象,并在 windows 窗体上显示信息。 此过程以 3 秒的提交间隔稳定运行约 20-25 分钟。在观察内存使用情况时,没有什么重要的可看的,也有点稳定。但是在这 20-25 分钟之后,服务器会在反序列化 tcp-stream 时抛出 StackOverflowException,尤其是在从 byte[]-array 设置 Image 属性时。

我彻底搜索了递归或无限循环,关于它发生在数千个成功间隔之后的事实,我几乎无法想象。

    public byte[] ImageBase
    {
        get
        {
            MemoryStream ms = new MemoryStream();
            _screen.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            return ms.GetBuffer();
        }
        set
        {
            if (_screen != null) _screen.Dispose(); //preventing well-known image memory leak
            MemoryStream ms = new MemoryStream(value);
            try
            {
                _screen = Image.FromStream(ms); //<< EXCEPTION THROWING HERE
            }
            catch (StackOverflowException ex) //thx to new CLR management this wont work anymore -.-
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
            }
            ms.Dispose();
            ms = null;
        }
    }

我希望不需要更多代码,否则会变得非常复杂...

请帮忙,我一点头绪都没有了

谢谢 克里斯

【问题讨论】:

  • 不知道你在 _screen = Image.FromStream(ms) 中做了什么,也许你不小心设置了 ImageBase?
  • 你真的应该把每个 MemoryStream 的使用放到一个 using() 块中,这样更容易看到正确处理的内容!
  • 尝试将堆栈跟踪的日志记录到您的 AppDomain.UnhandledException 事件中......当您的 try-catch 没有时应该触发该事件。我们真的需要一个堆栈跟踪来追踪这个问题msdn.microsoft.com/en-us/library/…
  • 不确定这是否能解决问题,但 ms.Dispose() 命令应该在 finally 子句中。
  • 关于堆栈溢出的一个堆栈溢出问题是递归,你怎么能说没有呢?

标签: c# .net image memorystream stack-overflow


【解决方案1】:

我怀疑不是您发布的代码,而是从 TCP 流中读取的代码使堆栈增长。 Image.FromStream 期间压死骆驼的稻草这一事实可能无关紧要。我经常看到人们编写包含自调用代码的套接字处理代码(有时是间接的,例如 A -> B -> A -> B)。您应该检查该代码并将其发布在此处供我们查看。

【讨论】:

  • 哦,如果您查看异常详细信息,您应该能够看到溢出时您的调用堆栈是什么样的。
  • 这里是... Listen()-Answer()-Listen()-Answer() 被递归调用 -.- 昨天已经发现了这个但忘记在这里设置这个为“已解决” .. 很抱歉,但非常感谢您的帮助 ;)
【解决方案2】:

您可能想阅读此内容。 Loading an image from a stream without keeping the stream open

似乎有可能在堆栈或其他最终会破坏堆栈的对象上维护流。

我的建议是抓住byte[] 并等到最后一刻解码并绘制它。然后立即处理图像。然后您的 get/set 将设置/获取byte[]。然后,您将实现一个自定义绘图例程,该例程将解码当前的byte[] 并绘制它,确保不会占用任何不必要的资源。

更新

如果您有办法让我们获得完整的堆栈跟踪,我们可能会提供进一步的帮助。我开始认为这不是我描述的问题。我创建了一个示例程序,它创建了 10,000 个图像,就像您在 setter 中所做的那样,并且没有问题。如果您每 3 秒发送一次图像,则每分钟 30 张图像乘以 20 分钟,即只有 600 张图像。

我对此问题的解决方案非常感兴趣。我稍后会回来。

有一些可能性,但是,远程。

  • Image.FromStream 正在尝试处理无效/损坏的字节 [],并且该方法以某种方式使用递归来解码位图。极不可能。
  • 没有在您认为的地方抛出异常。如果可能的话,完整的堆栈跟踪将非常有帮助。正如您所说,您无法捕获 StackOverflowException。如果您通过调试器运行它,我相信有这方面的规定。

【讨论】:

  • 另外,这不一定是任何原因——“getter”中的 MemoryStream 应该被丢弃,因为它是 IDisposable。
  • @Dave 好电话我错过了那个。如果他只持有 byte[],那么希望这将缓解他的大部分分配问题。
【解决方案3】:

我不确定它是否相关,但 Image.FromStream 的 MSDN 文档指出 您必须在图像的生命周期内保持流打开。

【讨论】:

  • 不,我不会让它保持打开状态;)它现在就像一个魅力;)
猜你喜欢
  • 2010-10-21
  • 2016-10-06
  • 1970-01-01
  • 2014-10-13
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-31
相关资源
最近更新 更多