代码之家  ›  专栏  ›  技术社区  ›  Stormenet

GC在一段时间后包含许多固定的对象

  •  4
  • Stormenet  · 技术社区  · 16 年前

    我在不断地实例化一个COM包装器,然后让GC收集它(不是强制的)时遇到了一个奇怪的现象。

    我在WinCE x86的.NET CF上测试这个。使用.NET Compact Framework远程监视器监视性能。本机内存通过平台生成器工具包中的Windows CE远程性能监视器进行跟踪。

    在创建的前1000个实例中,PerfMon中的每个计数器似乎都正常:

    • GC堆上下移动,但平均值保持不变
    • 固定对象为0
    • 本机内存保持相同的平均值

    但是,在这1000个(大约)之后,固定对象计数器将上升,不再计数下降。但是,内存使用率保持不变。

    我不知道从这些信息中得出什么结论…这是计数器中的错误吗?这是我的软件中的错误吗?

    [编辑]

    我确实注意到,固定对象计数器在GC稳定后,一旦使用的总字节数开始增加,而对象没有被压缩计数器移动。

    The graphic of the counters http://files.stormenet.be/gc_pinnedobj.jpg

    [/编辑]

    相关代码如下:

        private void pButton6_Click(object sender, EventArgs e) {
            if (_running) {
                _running = false;
                return;
            }
            _loopcount = 0;
            _running = true;
    
            Thread d = new Thread(new ThreadStart(LoopRun));
            d.Start();
        }
    
        private void LoopRun() {
            while (_running) {
                CreateInstances();
                _loopcount++;
                RefreshLabel();
            }
        }
    
        void CreateInstances() {
            List<Ppb.Drawing.Image> list = new List<Ppb.Drawing.Image>();
            for (int i = 0; i < 10; i++) {
                Ppb.Drawing.Image g = resourcesObj.someBitmap;
                list.Add(g);
            }
    
        }
    

    图像对象包含alphaImage:

        public sealed class AlphaImage : IDisposable {
        IImage _image;
        Size _size;
        IntPtr _bufferPtr;
    
        public static AlphaImage CreateFromBuffer(byte[] buffer, long size) {
            AlphaImage instance = new AlphaImage();
            IImage img;
            instance._bufferPtr = Marshal.AllocHGlobal((int)size);
            Marshal.Copy(buffer, 0, instance._bufferPtr, (int)size);
            GetIImagingFactory().CreateImageFromBuffer(instance._bufferPtr, (uint)size, BufferDisposalFlag.BufferDisposalFlagGlobalFree, out img);
            instance.SetImage(img);
            return instance;
        }
    
        void SetImage(IImage image) {
            _image = image;
            ImageInfo imgInfo;
            _image.GetImageInfo(out imgInfo);
            _size = new Size((int)imgInfo.Width, (int)imgInfo.Height);
        }
    
        ~AlphaImage() {
            Dispose();
        }
    
        #region IDisposable Members
    
        public void Dispose() {
            Marshal.FinalReleaseComObject(_image);
        }
    }
    
    2 回复  |  直到 16 年前
        1
  •  3
  •   ctacke    16 年前

    我怀疑这是转速的问题。我们这里没有的是对ppb的任何洞察。绘画的东西。我看到一个潜在的问题的地方是找工厂电话。它是做什么的?这可能只是一个单身汉,但这是我要追求的。

    我也看到了一个可分配的全局,但我看不到任何一个分配被释放。现在这就是我要关注的地方。

        2
  •  4
  •   Jon Skeet    16 年前

    好吧,您的代码中有一个bug,因为您创建了很多IDisposable实例,并且从未对它们调用Dispose。我希望定稿人最终会参与进来,但他们不应该真的是必要的。在您的生产代码中,您是否适当地处理了所有东西——如果没有,是否有一些原因您不能处理?

    如果您在alphaImage终结器中放置了一些日志记录(检测AppDomain卸载和应用程序关闭,在这些情况下不记录!)它是否显示正在调用的终结器?

    编辑:一个可能的问题 不是 咬你,但可能仍然值得修复-如果对CreateImageFromBuffer的调用由于任何原因失败,那么你仍然拥有由allochGlobal创建的内存,而这目前将被泄漏。我怀疑这不是问题所在,或者它会爆炸得更厉害,但这是值得考虑的。