使用反射查找未收集对象的原因 [英] Using Reflection to locate causes of uncollected objects

查看:55
本文介绍了使用反射查找未收集对象的原因的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在保留我的一些对象的WeakReference,以跟踪在用户认为它们已删除它们之后是否仍在徘徊.

就我所知,如果您仅维护对对象的弱引用,除非有防止阻止引用的引用,否则它将被收集.

因此,既然我已经找到了一个挥之不去的物体,我很想知道它在引用什么! (我有一个相当全面的系统来维护和破坏参考,但显然我错过了一些东西)


现在,一种解决方案是通过使用反射提取成员并递归地迭代环境(包括静态类),从主Form向下遍历整个对象树.我很自信我可以写这篇文章,但是由于对象可以非周期性地互相引用,因此有效的循环检测是一个问题,并且有很多警告,...因此,如果有人已经写过这篇文章,我很想知道!

有人听说过这样的工具吗?

如果确实存在,我会写的!
谢谢,

I''ve been keeping WeakReference''s of some of my objects to track whether they are lingering after the user believes they have deleted them.

So far as im aware, if you only maintain a weak reference to an object it will be collected unless there is a reference preventing collection.

So, now that ive found an object lingering, Id love to know what is referencing it! (i have a fairly comprehensive system for maintaining and breaking references, but clearly im missing something)


Now, one solution is to traverse the entire tree of objects from the main Form down, by using reflection to extract members and recursively iterate the environment (including static classes). Im confident I could write this, but as objects can reference one another acyclically, efficient cycle detection is an issue and there are lots of caveats,... so if someone has already written this, Id love to know!!

Has anyone heard of such a tool?

I''ll write it if it doenst exist!
Thanks

推荐答案

不幸的是,我不知道您维护引用的系统.基于正确使用弱引用的技术可能非常全面(因为您维护系统是这样);目的之一是避免遍历所有引用.您确定您不会有点复杂吗?您能否分享这个想法及其动机? -非常有趣.

无论如何,这可能是一个单独的问题.您是否只是想遍历一棵对象树,但认为引用是非循环的-您需要清理一下概念.

根据定义,树不是循环的,因此您知道如何遍历它.如果它至少有一个循环-停止将其称为树.它是不是树的对象图.基本上,树的定义是没有循环的图. -案件结案. :)

也许您认为还不清楚:如何遍历引用. :)好的,有一种简单的标准"方式.
您递归遍历图形,然后将所有发现的节点放到某个字典中-仅一次(字典被设计用于通过可以作为对象引用的键进行快速搜索,并保持唯一性).
如果已经在字典中找到某个对象,请中断此递归,转到下一个对象.

这只是个主意.为了在代码中进行说明,我需要了解您的对象模型.如果您自己做起来会更容易.无论如何,请问您是否还有其他问题.
Unfortunately, I don''t know your system of maintaining references. The techniques based on proper use of weak references can be really comprehensive (as you maintain your system is); and one of the purposes is to avoid traversing all the references. Are you sure you''re not over-complicating a bit? Could you share the idea and its motivation? -- very interesting.

Anyway, this can be a separate issue. Is you simply want to traverse a tree of objects, but think the references are acyclic -- you need to clean up your notions.

A tree if not cyclic by definition, so you know how to traverse it. If it has at least one cycle -- stop calling it a tree. It is an object graphs which is not a tree. Basically, a definition of the tree is a graph without cycles. -- case closed. :)

Perhaps you think it''s still not clear: what to do to traverse references. :) . All right, there is a simple "standard" way.
You traverse you graph recursively, and put all the node discovered on some dictionary -- only once (dictionaries are designed for fast search by a key which could be an object reference, and maintaining uniqueness).
If some object is found in dictionary already, break the recursion at this point, go to next object.

This is just the idea. To illustrate it in code I would need to know your object model. If could be easier for you to do it by yourself. Anyway, ask if you have any further questions.


实际上,..刚刚找到了这个: http://memprofiler.com/snapshotviews.aspx [ ^ ]

现在尝试...
actually,.. just found this: http://memprofiler.com/snapshotviews.aspx[^]

trying now,..


逻辑非常简单,因此决定还是编写代码.

这还算正常,所以不要烦我尝试,直到我停止尝试迭代值类型为止.

不会花很长时间,但是现在不能被打扰,所以要玩一些BFBC2! :-D

将在一个小时左右内解决..在此期间,任何想法都会一如既往:)


Logic is pretty simple so decided to write the code up anyway.

THIS ISNT WORKING YET so dont bother trying until I stop it from trying to iterate value types.

Wont take long, but cant be arsed just now so going to play some BFBC2! :-D

Will fix in an hour or so.. in the mean time any thoughts appreciated as always :)


<pre lang="cs">
using System;
using System.Collections.Generic;
using System.Reflection;

   /// <summary>
   /// locate all references of the specified object
   /// </summary>
   public static class avRefFinder
   {
       /// <summary>
       /// locate all references to object "toFind" within object network "entry"
       /// for example:
       /// FindRefs(menuButton23, Form1);
       /// </summary>
       /// <param name="toFind">an object of any type which is referred to</param>
       /// <param name="entry">the starting point for the search</param>
       /// <returns></returns>
       public static List<Stack<object>> FindRefs(object toFind, object entry)
       {
           List<Stack<object> > foundStacks = new List<Stack<object> >();
           Stack<object> curStack = new Stack<object>();
           curStack.Push(entry);
           FindRefsWorker(toFind, entry, curStack, ref foundStacks);
           objDict.Clear();
           return foundStacks;
       }
       static void FindRefsWorker(object toFind, object entry, Stack<object> curStack, ref List<Stack<object>> foundStacks)
       {
           FieldInfo []fields = entry.GetType().GetFields();
           PropertyInfo[] props = entry.GetType().GetProperties();
           foreach (FieldInfo inf in fields)
           {
               object current = inf.GetValue(entry);
               if (current != null && !objDict.Contains(current))
               {
                   objDict.Add(current);
                   curStack.Push(current);
                   if (object.ReferenceEquals(current, toFind))
                       foundStacks.Add(curStack);
                   FindRefsWorker(toFind, current, curStack, ref foundStacks);
                   curStack.Pop();
               }
           }
           foreach (PropertyInfo inf in props)
           {
               if (inf.CanRead)
               {
                   MethodInfo minf = inf.GetGetMethod();
                   object current = minf.Invoke(entry, new object[] { entry });
                   if (current != null && !objDict.Contains(current))
                   {
                       objDict.Add(current);
                       curStack.Push(current);
                       if (object.ReferenceEquals(current, toFind))
                           foundStacks.Add(curStack);
                       FindRefsWorker(toFind, current, curStack, ref foundStacks);
                       curStack.Pop();
                   }
               }
           }
       }
       static HashSet<object> objDict = new HashSet<object>();
   }



这篇关于使用反射查找未收集对象的原因的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆