首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MemoryStream泄漏

MemoryStream泄漏
EN

Stack Overflow用户
提问于 2012-09-07 14:37:16
回答 2查看 1.9K关注 0票数 7

谁能告诉我们下面的代码出了什么问题?我们这里有一个对象序列化程序,它应该返回传递给它的任何对象的XML字符串。

我们一直在为这个问题挠头,因为我们有一个程序多次调用它,我们看到我们的内存使用率达到了极高的水平(甚至在程序完成后仍然保持在那里)。我们找过了,但一无所获。流对象在"using“语句中,所以我们认为这应该是自己处理的。请帮帮忙。

代码语言:javascript
复制
    public static string ToXML(this IMessage m)
    {          
        try
        {
            var serializer = SerializerFactory.Create(m.GetType());
            using (var stream = new MemoryStream())
            {
                serializer.Serialize(new[] { m }, stream);
                stream.Position = 0;
                var s = Encoding.ASCII.GetString(stream.ToArray());
                return s;
            }
        }
        catch (Exception e)
        {
            return string.Format("Message unserializable: {0}", e.Message);
        }
    }

顺便说一句,SerializerFactory看起来像这样:

代码语言:javascript
复制
public class SerializerFactory
{
    public static IMessageSerializer Create(Type t)
    {
        var types = new List<Type> { t };
        var mapper = new MessageMapper();
        mapper.Initialize(types);
        var serializer = new XmlMessageSerializer(mapper);

        serializer.Initialize(types);

        return serializer;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-07 14:51:50

这段代码没有什么大问题;请注意,using本质上是MemoryStream上的无操作,因为它只有托管资源,而托管资源是GC的域;GC通常不会太担心,直到它收集了一些内存,所以我不会强调太多-或者:如果有问题,可能不是这个问题。

但是,一个观察结果是,您可以在编码步骤中避免使用缓冲区:

代码语言:javascript
复制
var s = Encoding.ASCII.GetString(stream.GetBuffer(), 0, (int)stream.Length);

实际上,默认情况下我会倾向于使用UTF8,而不是ASCII码。

最后想一想:你的SerializerFactory本身是不是在做一些泄露的事情?例如,您是否正在通过任何更复杂的构造函数创建new XmlSerializer(...)?最简单的形式:

代码语言:javascript
复制
new XmlSerializer(typeof(SomeType));

很好-它在内部缓存每个类型的内部/实际序列化程序,并为以这种方式创建的每个XmlSerializer实例重用它。但是,它不会为更复杂的构造函数重载执行此缓存:它每次都会创建并加载一个新的动态程序集。以这种方式加载的程序集永远不会卸载-所以,是的,这可能会导致内存泄漏。我非常想看看序列化程序实例是如何创建的,看看这是否是真正的问题。请注意,通过在工厂中创建自己的序列化程序缓存,通常可以非常容易地修复这些情况:

代码语言:javascript
复制
public class SerializerFactory
{
    // hashtable has better threading semantics than dictionary, honest!
    private static readonly Hashtable cache = new Hashtable();
    public static IMessageSerializer Create(Type t)
    {
        var found = (IMessageSerializer)cache[t];
        if(found != null) return found;

        lock(cache)
        {   // double-checked
            found = (IMessageSerializer)cache[t];
            if(found != null) return found;

            var types = new List<Type> { t };
            var mapper = new MessageMapper();
            mapper.Initialize(types);
            var serializer = new XmlMessageSerializer(mapper);

            serializer.Initialize(types);

            cache[t] = serializer;

            return serializer;
        }
    }
}
票数 7
EN

Stack Overflow用户

发布于 2012-09-07 14:57:04

内存泄漏不会发生在MemoryStream上,它实际上发生在XmlSerializer

“XmlSerializer构造函数的这个重载不会缓存动态生成的程序集,而是在每次实例化新的XmlSerializer时生成新的临时程序集!应用程序正在以临时程序集的形式泄漏非托管内存。“

看看这篇文章:

http://msdn.microsoft.com/en-us/magazine/cc163491.aspx

而不是每次都创建XmlSerializer,您需要为每个类型缓存,以解决您的问题。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12312961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档